Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add demangle option to collapsers #132

Merged
merged 6 commits into from
Jul 2, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ lazy_static = "1.3.0"
fnv = "1.0.3"
itoa = "0.4.3"
indexmap = "1.0"
symbolic-common = "6.1.3"
symbolic-demangle = "6.1.3"

[dev-dependencies]
pretty_assertions = "0.6"
Expand Down
5 changes: 5 additions & 0 deletions src/bin/collapse-dtrace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ struct Opt {
#[structopt(long = "includeoffset")]
includeoffset: bool,

/// Demangle function names
#[structopt(long = "demangle")]
demangle: bool,

/// perf script output file, or STDIN if not specified
infile: Option<PathBuf>,
}
Expand All @@ -40,6 +44,7 @@ impl Opt {
self.infile,
Options {
includeoffset: self.includeoffset,
demangle: self.demangle,
},
)
}
Expand Down
5 changes: 5 additions & 0 deletions src/bin/collapse-perf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ struct Opt {
#[structopt(short = "v", long = "verbose", parse(from_occurrences))]
verbose: usize,

/// Demangle function names
#[structopt(long = "demangle")]
demangle: bool,

/// perf script output file, or STDIN if not specified
infile: Option<PathBuf>,
}
Expand All @@ -69,6 +73,7 @@ impl Opt {
annotate_jit: self.annotate_jit || self.annotate_all,
annotate_kernel: self.annotate_kernel || self.annotate_all,
event_filter: self.event_filter,
demangle: self.demangle,
},
)
}
Expand Down
21 changes: 18 additions & 3 deletions src/collapse/dtrace.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use super::Collapse;
use fnv::FnvHashMap;
use log::warn;
use std::borrow::Cow;
use std::collections::VecDeque;
use std::io;
use std::io::prelude::*;
use symbolic_demangle::demangle;

/// Settings that change how frames are named from the incoming stack traces.
///
Expand All @@ -12,6 +14,9 @@ use std::io::prelude::*;
pub struct Options {
/// include function offset (except leafs)
pub includeoffset: bool,

/// Demangle function names
pub demangle: bool,
}

/// A stack collapser for the output of dtrace `ustrace()`.
Expand Down Expand Up @@ -182,8 +187,17 @@ impl Folder {
frame = Self::uncpp(frame);
}

if frame.is_empty() {
frame = "-";
let frame = if frame.is_empty() {
Cow::Owned("-".to_owned())
jasonrhansen marked this conversation as resolved.
Show resolved Hide resolved
} else if self.opt.demangle {
let mut parts = frame.split('`');
jasonrhansen marked this conversation as resolved.
Show resolved Hide resolved
if let (Some(pname), Some(func)) = (parts.next(), parts.next()) {
Cow::Owned(format!("{}`{}", pname, demangle(func)))
} else {
Cow::Borrowed(frame)
}
} else {
Cow::Borrowed(frame)
};

if has_inlines {
Expand All @@ -207,7 +221,7 @@ impl Folder {
} else if has_semicolon {
self.stack.push_front(frame.replace(';', ":"))
} else {
self.stack.push_front(frame.to_owned())
self.stack.push_front(frame.to_string())
}
}

Expand All @@ -231,6 +245,7 @@ impl Folder {
stack_str.push_str(&e);
}
}

// count it!
*self.occurrences.entry(stack_str).or_insert(0) += count;
// reset for the next event
Expand Down
11 changes: 11 additions & 0 deletions src/collapse/perf.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use super::Collapse;
use fnv::FnvHashMap;
use log::warn;
use std::borrow::Cow;
use std::collections::VecDeque;
use std::io;
use std::io::prelude::*;
use symbolic_demangle::demangle;

const TIDY_GENERIC: bool = true;
const TIDY_JAVA: bool = true;
Expand Down Expand Up @@ -32,6 +34,9 @@ pub struct Options {
/// Annotate kernel functions with a `_[k]` suffix.
pub annotate_kernel: bool,

/// Demangle function names
pub demangle: bool,

/// Only consider samples of the given event type (see `perf list`).
///
/// If this option is set to `None`, it will be set to the first encountered event type.
Expand Down Expand Up @@ -318,6 +323,12 @@ impl Folder {
return;
}

let rawfunc = if self.opt.demangle {
demangle(rawfunc)
} else {
Cow::Borrowed(rawfunc)
};

// Support Java inlining by splitting on "->". After the first func, the
// rest are annotated with "_[i]" to mark them as inlined.
// See https://github.com/brendangregg/FlameGraph/pull/89.
Expand Down
23 changes: 20 additions & 3 deletions tests/collapse-dtrace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use std::io::{self, BufReader, Cursor};
use std::process::{Command, Stdio};

fn test_collapse_dtrace(test_file: &str, expected_file: &str, options: Options) -> io::Result<()> {
test_collapse(Folder::from(options), test_file, expected_file)
test_collapse(Folder::from(options), test_file, expected_file, false)
}

fn test_collapse_dtrace_logs<F>(input_file: &str, asserter: F)
Expand Down Expand Up @@ -43,6 +43,7 @@ fn collapse_dtrace_compare_to_upstream_with_offsets() {
result_file,
Options {
includeoffset: true,
demangle: false,
},
)
.unwrap()
Expand Down Expand Up @@ -76,6 +77,7 @@ fn collapse_dtrace_compare_to_flamegraph_bug() {
result_file,
Options {
includeoffset: true,
demangle: false,
},
)
.unwrap()
Expand Down Expand Up @@ -108,6 +110,21 @@ fn collapse_dtrace_scope_with_no_argument_list() {
test_collapse_dtrace(test_file, result_file, Options::default()).unwrap()
}

#[test]
fn collapse_dtrace_demangle() {
let test_file = "./tests/data/collapse-dtrace/mangled.txt";
let result_file = "./tests/data/collapse-dtrace/results/demangled.txt";
test_collapse_dtrace(
test_file,
result_file,
Options {
includeoffset: false,
demangle: true,
},
)
.unwrap()
}

#[test]
fn collapse_dtrace_cli() {
let input_file = "./flamegraph/example-dtrace-stacks.txt";
Expand All @@ -120,7 +137,7 @@ fn collapse_dtrace_cli() {
.output()
.expect("failed to execute process");
let expected = BufReader::new(File::open(expected_file).unwrap());
compare_results(Cursor::new(output.stdout), expected, expected_file);
compare_results(Cursor::new(output.stdout), expected, expected_file, false);

// Test with STDIN
let mut child = Command::cargo_bin("inferno-collapse-dtrace")
Expand All @@ -134,5 +151,5 @@ fn collapse_dtrace_cli() {
io::copy(&mut input, stdin).unwrap();
let output = child.wait_with_output().expect("Failed to read stdout");
let expected = BufReader::new(File::open(expected_file).unwrap());
compare_results(Cursor::new(output.stdout), expected, expected_file);
compare_results(Cursor::new(output.stdout), expected, expected_file, false);
}
6 changes: 3 additions & 3 deletions tests/collapse-guess.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use std::io::{self, BufReader, Cursor};
use std::process::{Command, Stdio};

fn test_collapse_guess(test_file: &str, expected_file: &str) -> io::Result<()> {
test_collapse(Folder {}, test_file, expected_file)
test_collapse(Folder {}, test_file, expected_file, true)
}

fn test_collapse_guess_logs<F>(input_file: &str, asserter: F)
Expand Down Expand Up @@ -116,7 +116,7 @@ fn collapse_guess_cli() {
.output()
.expect("failed to execute process");
let expected = BufReader::new(File::open(expected_file).unwrap());
compare_results(Cursor::new(output.stdout), expected, expected_file);
compare_results(Cursor::new(output.stdout), expected, expected_file, true);

// Test with STDIN
let mut child = Command::cargo_bin("inferno-collapse-guess")
Expand All @@ -130,5 +130,5 @@ fn collapse_guess_cli() {
io::copy(&mut input, stdin).unwrap();
let output = child.wait_with_output().expect("Failed to read stdout");
let expected = BufReader::new(File::open(expected_file).unwrap());
compare_results(Cursor::new(output.stdout), expected, expected_file);
compare_results(Cursor::new(output.stdout), expected, expected_file, true);
}
36 changes: 32 additions & 4 deletions tests/collapse-perf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,18 @@ use std::io::{self, BufReader, Cursor};
use std::path::Path;
use std::process::{Command, Stdio};

fn test_collapse_perf(test_file: &str, expected_file: &str, options: Options) -> io::Result<()> {
test_collapse(Folder::from(options), test_file, expected_file)
fn test_collapse_perf(
test_file: &str,
expected_file: &str,
options: Options,
strip_quotes: bool,
) -> io::Result<()> {
test_collapse(
Folder::from(options),
test_file,
expected_file,
strip_quotes,
)
}

fn test_collapse_perf_logs<F>(input_file: &str, asserter: F)
Expand Down Expand Up @@ -87,6 +97,7 @@ macro_rules! collapse_perf_tests_inner {
test_path.join(test_file).to_str().unwrap(),
results_path.join(result_file).to_str().unwrap(),
options_from_vec(options),
true
)

.unwrap()
Expand Down Expand Up @@ -211,6 +222,7 @@ fn collapse_perf_example_perf_stacks() {
"./flamegraph/example-perf-stacks.txt.gz",
"./tests/data/collapse-perf/results/example-perf-stacks-collapsed.txt",
Default::default(),
false,
)
.unwrap();
}
Expand Down Expand Up @@ -255,6 +267,22 @@ fn collapse_perf_should_warn_about_weird_input_lines() {
);
}

#[test]
fn collapse_perf_demangle() {
let test_file = "./tests/data/collapse-perf/mangled.txt";
let result_file = "./tests/data/collapse-perf/results/demangled.txt";
test_collapse_perf(
test_file,
result_file,
Options {
demangle: true,
..Default::default()
},
false,
)
.unwrap()
}

#[test]
fn collapse_perf_cli() {
let input_file = "./flamegraph/test/perf-vertx-stacks-01.txt";
Expand All @@ -268,7 +296,7 @@ fn collapse_perf_cli() {
.output()
.expect("failed to execute process");
let expected = BufReader::new(File::open(expected_file).unwrap());
compare_results(Cursor::new(output.stdout), expected, expected_file);
compare_results(Cursor::new(output.stdout), expected, expected_file, true);

// Test with STDIN
let mut child = Command::cargo_bin("inferno-collapse-perf")
Expand All @@ -283,5 +311,5 @@ fn collapse_perf_cli() {
io::copy(&mut input, stdin).unwrap();
let output = child.wait_with_output().expect("Failed to read stdout");
let expected = BufReader::new(File::open(expected_file).unwrap());
compare_results(Cursor::new(output.stdout), expected, expected_file);
compare_results(Cursor::new(output.stdout), expected, expected_file, true);
}
12 changes: 8 additions & 4 deletions tests/collapse_common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub(crate) fn test_collapse<C>(
mut collapser: C,
test_filename: &str,
expected_filename: &str,
strip_quotes: bool,
) -> io::Result<()>
where
C: Collapse,
Expand Down Expand Up @@ -53,7 +54,7 @@ where
eprintln!("test output in {}", tm.display());
}
// and then compare
compare_results(result, expected, expected_filename);
compare_results(result, expected, expected_filename, strip_quotes);
Ok(return_value)
}

Expand All @@ -68,16 +69,19 @@ where
testing_logger::validate(asserter);
}

pub(crate) fn compare_results<R, E>(result: R, mut expected: E, expected_file: &str)
pub(crate) fn compare_results<R, E>(result: R, mut expected: E, expected_file: &str, strip_quotes: bool)
where
R: BufRead,
E: BufRead,
{
let mut buf = String::new();
let mut line_num = 1;
for line in result.lines() {
// Strip out " and ' since perl version does.
let line = line.unwrap().replace("\"", "").replace("'", "");
let line = if strip_quotes {
line.unwrap().replace("\"", "").replace("'", "")
} else {
line.unwrap()
};
if expected.read_line(&mut buf).unwrap() == 0 {
panic!(
"\noutput has more lines than expected result file: {}",
Expand Down
Loading