From 52f199174bd69458a263dedb842e4df5bc62677b Mon Sep 17 00:00:00 2001 From: pbmtp Date: Wed, 9 Jun 2021 18:29:03 +0200 Subject: [PATCH 1/5] WIP: Add simple pmc collapse to replace stackcollapse-pmc.pl. --- Cargo.toml | 5 + benches/collapse.rs | 6 +- compare.sh | 9 + src/bin/collapse-pmc.rs | 86 +++++ src/collapse/guess.rs | 12 +- src/collapse/mod.rs | 7 + src/collapse/pmc.rs | 460 +++++++++++++++++++++++++++ tests/data/collapse-pmc/dd.txt | 209 ++++++++++++ tests/data/collapse-pmc/iperf3.txt | 192 +++++++++++ tests/data/collapse-pmc/large.txt.gz | Bin 0 -> 117871 bytes tests/data/collapse-pmc/shared.txt | 39 +++ tests/data/collapse-pmc/shared2.txt | 26 ++ tests/data/collapse-pmc/simple.txt | 18 ++ 13 files changed, 1065 insertions(+), 4 deletions(-) create mode 100644 src/bin/collapse-pmc.rs create mode 100644 src/collapse/pmc.rs create mode 100644 tests/data/collapse-pmc/dd.txt create mode 100644 tests/data/collapse-pmc/iperf3.txt create mode 100644 tests/data/collapse-pmc/large.txt.gz create mode 100644 tests/data/collapse-pmc/shared.txt create mode 100644 tests/data/collapse-pmc/shared2.txt create mode 100644 tests/data/collapse-pmc/simple.txt diff --git a/Cargo.toml b/Cargo.toml index b765587a..f54419d2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -80,6 +80,11 @@ name = "inferno-collapse-vtune" path = "src/bin/collapse-vtune.rs" required-features = ["cli"] +[[bin]] +name = "inferno-collapse-pmc" +path = "src/bin/collapse-pmc.rs" +required-features = ["cli"] + [[bin]] name = "inferno-collapse-guess" path = "src/bin/collapse-guess.rs" diff --git a/benches/collapse.rs b/benches/collapse.rs index 716accd9..7b99ba84 100644 --- a/benches/collapse.rs +++ b/benches/collapse.rs @@ -2,13 +2,14 @@ use std::fs::File; use std::io::{self, Read}; use criterion::*; -use inferno::collapse::{dtrace, perf, sample, Collapse}; +use inferno::collapse::{dtrace, perf, sample, pmc, Collapse}; use lazy_static::lazy_static; use libflate::gzip::Decoder; const INFILE_DTRACE: &str = "flamegraph/example-dtrace-stacks.txt"; const INFILE_PERF: &str = "flamegraph/example-perf-stacks.txt.gz"; const INFILE_SAMPLE: &str = "tests/data/collapse-sample/large.txt.gz"; +const INFILE_PMC: &str = "tests/data/collapse-pmc/large.txt.gz"; const SAMPLE_SIZE: usize = 100; lazy_static! { @@ -96,7 +97,8 @@ macro_rules! benchmark_multi { benchmark_multi!(dtrace, "dtrace", INFILE_DTRACE); benchmark_multi!(perf, "perf", INFILE_PERF); benchmark_single!(sample, "sample", INFILE_SAMPLE); +benchmark_multi!(pmc, "pmc", INFILE_PMC); -criterion_group!(benches, dtrace, perf, sample); +criterion_group!(benches, dtrace, perf, pmc, sample); criterion_main!(benches); diff --git a/compare.sh b/compare.sh index ddabc208..f5ed5430 100755 --- a/compare.sh +++ b/compare.sh @@ -28,3 +28,12 @@ zcat < tests/data/collapse-sample/large.txt.gz > "$f" echo "==> sample <==" hyperfine --warmup 20 -m 50 "$BIN/inferno-collapse-sample $f" "./flamegraph/stackcollapse-sample.awk $f" rm "$f" + +echo +echo +cargo build --release --bin inferno-collapse-pmc +f=tests/data/collapse-pmc/large.txt +zcat < tests/data/collapse-pmc/large.txt.gz > "$f" +echo "==> pmc <==" +hyperfine --warmup 20 -m 50 "$BIN/inferno-collapse-pmc $f" "./flamegraph/stackcollapse-pmc.pl $f" +rm "$f" diff --git a/src/bin/collapse-pmc.rs b/src/bin/collapse-pmc.rs new file mode 100644 index 00000000..39a0eef6 --- /dev/null +++ b/src/bin/collapse-pmc.rs @@ -0,0 +1,86 @@ +use std::io; +use std::path::PathBuf; + +use env_logger::Env; +use inferno::collapse::pmc::{Folder, Options}; +use inferno::collapse::{Collapse, DEFAULT_NTHREADS}; +use lazy_static::lazy_static; +use structopt::StructOpt; + +lazy_static! { + static ref NTHREADS: String = format!("{}", *DEFAULT_NTHREADS); +} + +#[derive(Debug, StructOpt)] +#[structopt( + name = "inferno-collapse-pmc", + about, + after_help = "\ +[1] pmcstat must be used in callchain mode (-G). + For example: + To capture, use: + pmcstat -S unhalted-cycles -O pmc.out + To convert to callchain, you can use: + pmcstat -R pmc.out -z16 -G pmc.graph + Then collapse all stacks to flamegraph format + inferno-collapse-pmc pmc.graph +" +)] +struct Opt { + // ************* // + // *** FLAGS *** // + // ************* // + /// Silence all log output + #[structopt(short = "q", long = "quiet")] + quiet: bool, + + /// Verbose logging mode (-v, -vv, -vvv) + #[structopt(short = "v", long = "verbose", parse(from_occurrences))] + verbose: usize, + + // *************** // + // *** OPTIONS *** // + // *************** // + /// Number of threads to use + #[structopt( + short = "n", + long = "nthreads", + default_value = &NTHREADS, + value_name = "UINT" + )] + nthreads: usize, + + // ************ // + // *** ARGS *** // + // ************ // + #[structopt(value_name = "PATH")] + /// Pmcstat -G output file, or STDIN if not specified + infile: Option, +} + +impl Opt { + fn into_parts(self) -> (Option, Options) { + let mut options = Options::default(); + options.nthreads = self.nthreads; + (self.infile, options) + } +} + +fn main() -> io::Result<()> { + let opt = Opt::from_args(); + + // Initialize logger + if !opt.quiet { + env_logger::Builder::from_env(Env::default().default_filter_or(match opt.verbose { + 0 => "warn", + 1 => "info", + 2 => "debug", + _ => "trace", + })) + .format_timestamp(None) + .init(); + } + + let (infile, options) = opt.into_parts(); + Folder::from(options).collapse_file_to_stdout(infile.as_ref()) +} diff --git a/src/collapse/guess.rs b/src/collapse/guess.rs index c28526e9..60af53c1 100644 --- a/src/collapse/guess.rs +++ b/src/collapse/guess.rs @@ -3,7 +3,7 @@ use std::io::{self, Cursor}; use log::{error, info}; -use crate::collapse::{self, dtrace, perf, sample, vtune, Collapse}; +use crate::collapse::{self, dtrace, perf, sample, vtune, pmc, Collapse}; const LINES_PER_ITERATION: usize = 10; @@ -69,10 +69,17 @@ impl Collapse for Folder { }; let mut sample = sample::Folder::default(); let mut vtune = vtune::Folder::default(); + let mut pmc = { + let options = pmc::Options { + nthreads: self.opt.nthreads, + ..Default::default() + }; + pmc::Folder::from(options) + }; // Each Collapse impl gets its own flag in this array. // It gets set to true when the impl has been ruled out. - let mut not_applicable = [false; 4]; + let mut not_applicable = [false; 5]; let mut buffer = String::new(); loop { @@ -106,6 +113,7 @@ impl Collapse for Folder { try_collapse_impl!(dtrace, 1); try_collapse_impl!(sample, 2); try_collapse_impl!(vtune, 3); + try_collapse_impl!(pmc, 4); if eof { break; diff --git a/src/collapse/mod.rs b/src/collapse/mod.rs index 57d065fa..a4e2675c 100644 --- a/src/collapse/mod.rs +++ b/src/collapse/mod.rs @@ -35,6 +35,13 @@ pub mod sample; /// [crate-level documentation]: ../../index.html pub mod vtune; +/// Stack collapsing for the output of [`pmcstat`](https://www.freebsd.org/cgi/man.cgi?query=pmcstat&sektion=8) in callchain mode (-G). +/// +/// See the [crate-level documentation] for details. +/// +/// [crate-level documentation]: ../../index.html +pub mod pmc; + // DEFAULT_NTHREADS is public because we use it in the help text of the binaries, // but it doesn't need to be exposed to library users, hence #[doc(hidden)]. #[doc(hidden)] diff --git a/src/collapse/pmc.rs b/src/collapse/pmc.rs new file mode 100644 index 00000000..c542bbe6 --- /dev/null +++ b/src/collapse/pmc.rs @@ -0,0 +1,460 @@ +use std::collections::VecDeque; +use std::io::{self, BufRead}; + +use crate::collapse::common::{self, CollapsePrivate, Occurrences}; + +mod logging { + use log::warn; + + pub(super) fn weird_stack_line(line: &str) { + warn!("Weird stack line: {}", line); + } +} + +/// `pmcstat` folder configuration options. +#[derive(Clone, Debug)] +#[non_exhaustive] +pub struct Options { + /// The number of threads to use. + /// + /// Default is the number of logical cores on your machine. + pub nthreads: usize, +} + +impl Default for Options { + fn default() -> Self { + Self { + nthreads: *common::DEFAULT_NTHREADS, + } + } +} + +/// A stack collapser for the output of `pmcstat -G` (callchain mode). +/// +/// To construct one, either use `pmc::Folder::default()` or create an [`Options`] and use +/// `pmc::Folder::from(options)`. +pub struct Folder { + // State... + + /// The number of stacks per job to send to the threadpool. + nstacks_per_job: usize, + + /// Function entries on the stack in this entry thus far. + stack: VecDeque, + + /// Number of leading spaces (i.e. stack depth) found on last stack line + indent: Option, + + /// The called count found on last processed stack line + count: Option, + + // Options... + opt: Options, +} + +impl From for Folder { + fn from(mut opt: Options) -> Self { + if opt.nthreads == 0 { + opt.nthreads = 1; + } + Self { + nstacks_per_job: common::DEFAULT_NSTACKS_PER_JOB, + stack: VecDeque::default(), + indent: None, + count: None, + opt, + } + } +} + +impl Default for Folder { + fn default() -> Self { + Options::default().into() + } +} + +impl CollapsePrivate for Folder { + fn pre_process(&mut self, _reader: &mut R, _occurrences: &mut Occurrences) -> io::Result<()> + where + R: io::BufRead, + { + // We do not need any special pre-processing + Ok(()) + } + + fn collapse_single_threaded( + &mut self, + mut reader: R, + occurrences: &mut Occurrences, + ) -> io::Result<()> + where + R: io::BufRead, + { + // While there are still stacks left to process, process them... + let mut line_buffer = Vec::new(); + while !self.process_single_stack(&mut line_buffer, &mut reader, occurrences)? {} + + // Reset state... + self.stack.clear(); + self.indent = None; + self.count = None; + Ok(()) + } + + /// Determine if this format corresponds to the input data. + fn is_applicable(&mut self, input: &str) -> Option { + // First line is always of the form + // @ [ bool { + line.is_empty() + } + + fn clone_and_reset_stack_context(&self) -> Self { + Self { + nstacks_per_job: self.nstacks_per_job, + stack: VecDeque::default(), + indent: None, + count: None, + opt: self.opt.clone(), + } + } + + fn nstacks_per_job(&self) -> usize { + self.nstacks_per_job + } + + fn set_nstacks_per_job(&mut self, n: usize) { + self.nstacks_per_job = n; + } + + fn nthreads(&self) -> usize { + self.opt.nthreads + } + + fn set_nthreads(&mut self, n: usize) { + self.opt.nthreads = n; + } +} + +impl Folder { + /// Processes a stack. On success, returns `true` if at end of data; `false` otherwise. + fn process_single_stack( + &mut self, + line_buffer: &mut Vec, + reader: &mut R, + occurrences: &mut Occurrences, + ) -> io::Result + where + R: io::BufRead, + { + loop { + line_buffer.clear(); + if reader.read_until(0x0A, line_buffer)? == 0 { + if !self.stack.is_empty() { + self.after_stack(occurrences); + } + return Ok(true); + } + let line = String::from_utf8_lossy(line_buffer); + if line.starts_with('@') { + continue; + } + let line = line.trim_end(); + if line.is_empty() { + self.after_stack(occurrences); + return Ok(false); + } else { + self.on_stack_line(line, occurrences); + } + } + } + + /// Parse a stack line and extract and validate some fields + // We extract: + // - the size of the leading spaces + // - the percentage value (not used for now but just in case it is needed later) + // - the count between [ ] + // - the function name + // + // We ignore the module part "@ xxx" which is optionnaly present at the end of the line + // + // Ex: + // 08.91% [1318] acpi_cpu_c1 @ /boot/kernel/kernel + // 100.0% [1318] acpi_cpu_idle + // 100.0% [1318] cpu_idle_acpi + fn stack_line_parts(line: &str) -> Option<(usize, &str, usize, &str)> { + // count leading spaces + let indent = line.chars().position(|c| !c.is_whitespace()).unwrap_or(0); + + // Ex: " 54.00% [27] kern_clock_nanosleep" + let mut words = line[indent..].split_whitespace(); // TODO check performance vs multiple splitn() + + let percent = words.next(); + let count = words.next(); + let function = words.next(); + + match (percent, count, function) { + (Some(percent), Some(count), Some(function)) => { + // minimal validation '0%' -> 'x.y%' -> '100.0%' + let lpercent = percent.len(); + if lpercent >= 2 && percent.ends_with('%') { + // minimal validation '[numbers]' + let lcount = count.len(); + if lcount >= 3 && count.starts_with('[') && count.ends_with(']') { + if let Ok(count) = count[1..lcount - 1].parse() { + return Some((indent, &percent[..lpercent - 1], count, function)); + } + } + } + } + (_, _, _) => { + println!("not enough words, ignoring line"); + } + } + + None + } + + // we have a stack line that shows one stack entry from the preceeding event, like: + // + // 08.91% [1318] acpi_cpu_c1 @ /boot/kernel/kernel + // 100.0% [1318] acpi_cpu_idle + // 100.0% [1318] cpu_idle_acpi + // 100.0% [1318] cpu_idle + // 100.0% [1318] sched_idletd + // 100.0% [1318] fork_exit + fn on_stack_line(&mut self, line: &str, occurrences: &mut Occurrences) { + let parts = Self::stack_line_parts(&line); + match parts { + Some((indent, _, count, function)) => { + // detect shared stacks, i.e. stacks that share some elements + // for example: + // + // 01.17% [173] randomdev_encrypt @ /boot/kernel/kernel + // 95.95% [166] random_fortuna_read + // 100.0% [166] read_random_uio + // 100.0% [166] devfs_read_f + // 100.0% [166] kern_readv + // 100.0% [166] sys_read + // 100.0% [166] amd64_syscall + // 04.05% [7] read_random_uio + // 100.0% [7] devfs_read_f + // 100.0% [7] kern_readv + // 100.0% [7] sys_read + // 100.0% [7] amd64_syscall + // + // Or (a more complex one) + // + // 00.31% [2] 0xf4ae3 @ /lib/libc.so.7 + // 50.00% [1] 0x53c2f @ /usr/lib/libprivatessh.so.5 + // 50.00% [1] 0x3b25deb @ /usr/bin/clang-cpp + // 100.0% [1] 0x48c282e + // 100.0% [1] 0x48c73c8 + if self.indent.is_some() && indent <= self.indent.unwrap_or(0) { + // allocate a string that is long enough to hold the entire stack string + let mut stack_str = String::with_capacity( + self.stack.iter().fold(0, |a, s| a + s.len() + 1), + ); + + // add the stack entries + let mut first = true; + for e in self.stack.iter() { + if !first { + stack_str.push(';'); + } else { + first = false; + } + stack_str.push_str(&e); + } + + // count it! + assert!(self.count.is_some()); + occurrences.insert_or_add(stack_str, self.count.expect("count not found on previous line")); + + // pop as many element as needed to prepare for the next shared stack + self.stack.drain(.. self.stack.len() - indent); + } + + self.indent = Some(indent); + self.count = Some(count); + + // TODO annotate kernel functions with a `_[k]` suffix. + // TODO filter raw addresses + // TODO demangle C++ / Rust symbols + self.stack.push_front(function.to_string()); + }, + None => { + logging::weird_stack_line(line); + }, + } + } + + fn after_stack(&mut self, occurrences: &mut Occurrences) { + // end of stack, so emit stack entry + if !self.stack.is_empty() { + // allocate a string that is long enough to hold the entire stack string + let mut stack_str = String::with_capacity( + self.stack.iter().fold(0, |a, s| a + s.len() + 1), + ); + + // add the stack entries (if any) + let mut first = true; + for e in self.stack.drain(..) { + if !first { + stack_str.push(';'); + } else { + first = false; + } + stack_str.push_str(&e); + } + + // count it! + assert!(self.count.is_some()); + occurrences.insert_or_add(stack_str, self.count.expect("count not found on previous line")); + } + + // reset for next stack + self.stack.clear(); + self.indent = None; + self.count = None; + } +} + +#[cfg(test)] +mod tests { + use std::fs; + use std::io::Read; + use std::path::PathBuf; + + use lazy_static::lazy_static; + use pretty_assertions::assert_eq; + use rand::prelude::*; + + use super::*; + use crate::collapse::common; + use crate::collapse::Collapse; + + lazy_static! { + static ref INPUT: Vec = { + [ + "./tests/data/collapse-pmc/simple.txt", + "./tests/data/collapse-pmc/shared.txt", + "./tests/data/collapse-pmc/shared2.txt", + "./tests/data/collapse-pmc/dd.txt", + "./tests/data/collapse-pmc/iperf3.txt", + // "./tests/data/collapse-pmc/large.txt.gz", + ] + .iter() + .map(PathBuf::from) + .collect::>() + }; + } + + #[test] + fn test_collapse_multi_pmc() -> io::Result<()> { + let mut folder = Folder::default(); + common::testing::test_collapse_multi(&mut folder, &INPUT) + } + + #[test] + fn test_collapse_multi_pmc_simple() -> io::Result<()> { + let path = "./tests/data/collapse-pmc/simple.txt"; + let mut file = fs::File::open(path)?; + let mut bytes = Vec::new(); + file.read_to_end(&mut bytes)?; + let mut folder = Folder::default(); + ::collapse(&mut folder, &bytes[..], io::sink()) + } + + /// Varies the nstacks_per_job parameter and outputs the 10 fastests configurations by file. + /// + /// Command: `cargo test bench_nstacks_pmc --release -- --ignored --nocapture` + #[test] + #[ignore] + fn bench_nstacks_pmc() -> io::Result<()> { + let mut folder = Folder::default(); + common::testing::bench_nstacks(&mut folder, &INPUT) + } + + #[test] + #[ignore] + /// Fuzz test the multithreaded collapser. + /// + /// Command: `cargo test fuzz_collapse_pmc --release -- --ignored --nocapture` + fn fuzz_collapse_pmc() -> io::Result<()> { + let seed = thread_rng().gen::(); + println!("Random seed: {}", seed); + let mut rng = SmallRng::seed_from_u64(seed); + + let mut buf_actual = Vec::new(); + let mut buf_expected = Vec::new(); + let mut count = 0; + + let inputs = common::testing::read_inputs(&INPUT)?; + + loop { + let nstacks_per_job = rng.gen_range(1..=500); + let options = Options { + nthreads: rng.gen_range(2..=32), + }; + + for (path, input) in inputs.iter() { + buf_actual.clear(); + buf_expected.clear(); + + let mut folder = { + let mut options = options.clone(); + options.nthreads = 1; + Folder::from(options) + }; + folder.nstacks_per_job = nstacks_per_job; + ::collapse(&mut folder, &input[..], &mut buf_expected)?; + let expected = std::str::from_utf8(&buf_expected[..]).unwrap(); + + let mut folder = Folder::from(options.clone()); + folder.nstacks_per_job = nstacks_per_job; + ::collapse(&mut folder, &input[..], &mut buf_actual)?; + let actual = std::str::from_utf8(&buf_actual[..]).unwrap(); + + if actual != expected { + eprintln!( + "Failed on file: {}\noptions: {:#?}\n", + path.display(), + options + ); + assert_eq!(actual, expected); + } + } + + count += 1; + if count % 10 == 0 { + println!("Successfully ran {} fuzz tests.", count); + } + } + } +} diff --git a/tests/data/collapse-pmc/dd.txt b/tests/data/collapse-pmc/dd.txt new file mode 100644 index 00000000..f9181205 --- /dev/null +++ b/tests/data/collapse-pmc/dd.txt @@ -0,0 +1,209 @@ +@ CLOCK.HARD [2 samples] + +100.0% [2] spinlock_exit @ /boot/kernel/kernel + 50.00% [1] sleepq_timedwait + 100.0% [1] _sleep + 100.0% [1] pmclog_loop @ /boot/kernel/hwpmc.ko + 100.0% [1] fork_exit @ /boot/kernel/kernel + 50.00% [1] cpu_activeclock + 100.0% [1] cpu_idle + 100.0% [1] sched_idletd + 100.0% [1] fork_exit + +@ CLOCK.HARD [1 samples] + +100.0% [1] spinlock_exit @ /boot/kernel/kernel + 100.0% [1] cpu_activeclock + 100.0% [1] cpu_idle + 100.0% [1] sched_idletd + 100.0% [1] fork_exit + +@ CLOCK.HARD [251 samples] + +89.64% [225] randomdev_keystream @ /boot/kernel/kernel + 100.0% [225] random_fortuna_genbytes + 100.0% [225] random_fortuna_read + 100.0% [225] read_random_uio + 100.0% [225] devfs_read_f + 100.0% [225] dofileread + 100.0% [225] sys_read + 100.0% [225] amd64_syscall + +02.79% [7] copyout_nosmap_std @ /boot/kernel/kernel + 100.0% [7] uiomove_faultflag + 100.0% [7] read_random_uio + 100.0% [7] devfs_read_f + 100.0% [7] dofileread + 100.0% [7] sys_read + 100.0% [7] amd64_syscall + +02.39% [6] memset_std @ /boot/kernel/kernel + 100.0% [6] explicit_bzero + 100.0% [6] zfree + 100.0% [6] read_random_uio + 100.0% [6] devfs_read_f + 100.0% [6] dofileread + 100.0% [6] sys_read + 100.0% [6] amd64_syscall + +01.59% [4] spinlock_exit @ /boot/kernel/kernel + 100.0% [4] pmap_update_pde + 50.00% [2] pmap_promote_pde + 100.0% [2] pmap_enter + 100.0% [2] kmem_back_domain + 100.0% [2] kmem_malloc_domainset + 100.0% [2] malloc_large + 100.0% [2] malloc + 100.0% [2] read_random_uio + 100.0% [2] devfs_read_f + 100.0% [2] dofileread + 100.0% [2] sys_read + 100.0% [2] amd64_syscall + 50.00% [2] pmap_demote_pde_locked + 100.0% [2] pmap_remove + 100.0% [2] _kmem_unback + 100.0% [2] kmem_free + 100.0% [2] zfree + 100.0% [2] read_random_uio + 100.0% [2] devfs_read_f + 100.0% [2] dofileread + 100.0% [2] sys_read + 100.0% [2] amd64_syscall + +01.20% [3] vm_radix_insert @ /boot/kernel/kernel + 100.0% [3] vm_page_alloc_domain_after + 100.0% [3] kmem_back_domain + 100.0% [3] kmem_malloc_domainset + 100.0% [3] malloc_large + 100.0% [3] malloc + 100.0% [3] read_random_uio + 100.0% [3] devfs_read_f + 100.0% [3] dofileread + 100.0% [3] sys_read + 100.0% [3] amd64_syscall + +00.80% [2] 0xb768a @ /lib/libc.so.7 + 100.0% [2] 0x2042e0 @ /bin/dd + +00.40% [1] vm_reserv_free_page @ /boot/kernel/kernel + 100.0% [1] vm_page_free_prep + 100.0% [1] vm_page_free_toq + 100.0% [1] _kmem_unback + 100.0% [1] kmem_free + 100.0% [1] zfree + 100.0% [1] read_random_uio + 100.0% [1] devfs_read_f + 100.0% [1] dofileread + 100.0% [1] sys_read + 100.0% [1] amd64_syscall + +00.40% [1] zfree @ /boot/kernel/kernel + 100.0% [1] read_random_uio + 100.0% [1] devfs_read_f + 100.0% [1] dofileread + 100.0% [1] sys_read + 100.0% [1] amd64_syscall + +00.40% [1] vm_page_free_prep @ /boot/kernel/kernel + 100.0% [1] vm_page_free_toq + 100.0% [1] _kmem_unback + 100.0% [1] kmem_free + 100.0% [1] zfree + 100.0% [1] read_random_uio + 100.0% [1] devfs_read_f + 100.0% [1] dofileread + 100.0% [1] sys_read + 100.0% [1] amd64_syscall + +00.40% [1] vm_domain_allocate @ /boot/kernel/kernel + 100.0% [1] vm_reserv_alloc_page + 100.0% [1] vm_page_alloc_domain_after + 100.0% [1] kmem_back_domain + 100.0% [1] kmem_malloc_domainset + 100.0% [1] malloc_large + 100.0% [1] malloc + 100.0% [1] read_random_uio + 100.0% [1] devfs_read_f + 100.0% [1] dofileread + 100.0% [1] sys_read + 100.0% [1] amd64_syscall + +@ � [66 samples] + +87.88% [58] randomdev_keystream @ /boot/kernel/kernel + 100.0% [58] random_fortuna_genbytes + 100.0% [58] random_fortuna_read + 100.0% [58] read_random_uio + 100.0% [58] devfs_read_f + 100.0% [58] dofileread + 100.0% [58] sys_read + 100.0% [58] amd64_syscall + +06.06% [4] spinlock_exit @ /boot/kernel/kernel + 75.00% [3] pmap_update_pde + 66.67% [2] pmap_promote_pde + 100.0% [2] pmap_enter + 100.0% [2] kmem_back_domain + 100.0% [2] kmem_malloc_domainset + 100.0% [2] malloc_large + 100.0% [2] malloc + 100.0% [2] read_random_uio + 100.0% [2] devfs_read_f + 100.0% [2] dofileread + 100.0% [2] sys_read + 100.0% [2] amd64_syscall + 33.33% [1] pmap_demote_pde_locked + 100.0% [1] pmap_remove + 100.0% [1] _kmem_unback + 100.0% [1] kmem_free + 100.0% [1] zfree + 100.0% [1] read_random_uio + 100.0% [1] devfs_read_f + 100.0% [1] dofileread + 100.0% [1] sys_read + 100.0% [1] amd64_syscall + 25.00% [1] cpu_activeclock + 100.0% [1] cpu_idle + 100.0% [1] sched_idletd + 100.0% [1] fork_exit + +01.52% [1] copyout_nosmap_std @ /boot/kernel/kernel + 100.0% [1] uiomove_faultflag + 100.0% [1] read_random_uio + 100.0% [1] devfs_read_f + 100.0% [1] dofileread + 100.0% [1] sys_read + 100.0% [1] amd64_syscall + +01.52% [1] vm_reserv_free_page @ /boot/kernel/kernel + 100.0% [1] vm_page_free_prep + 100.0% [1] vm_page_free_toq + 100.0% [1] _kmem_unback + 100.0% [1] kmem_free + 100.0% [1] zfree + 100.0% [1] read_random_uio + 100.0% [1] devfs_read_f + 100.0% [1] dofileread + 100.0% [1] sys_read + 100.0% [1] amd64_syscall + +01.52% [1] memset_std @ /boot/kernel/kernel + 100.0% [1] explicit_bzero + 100.0% [1] zfree + 100.0% [1] read_random_uio + 100.0% [1] devfs_read_f + 100.0% [1] dofileread + 100.0% [1] sys_read + 100.0% [1] amd64_syscall + +01.52% [1] vm_page_free_prep @ /boot/kernel/kernel + 100.0% [1] vm_page_free_toq + 100.0% [1] _kmem_unback + 100.0% [1] kmem_free + 100.0% [1] zfree + 100.0% [1] read_random_uio + 100.0% [1] devfs_read_f + 100.0% [1] dofileread + 100.0% [1] sys_read + 100.0% [1] amd64_syscall + diff --git a/tests/data/collapse-pmc/iperf3.txt b/tests/data/collapse-pmc/iperf3.txt new file mode 100644 index 00000000..43653d86 --- /dev/null +++ b/tests/data/collapse-pmc/iperf3.txt @@ -0,0 +1,192 @@ +@ CLOCK.HARD [118 samples] + +50.00% [59] copyout_nosmap_std @ /boot/kernel/kernel + 100.0% [59] uiomove_faultflag + 100.0% [59] soreceive_generic + 100.0% [59] soreceive + 100.0% [59] dofileread + 100.0% [59] sys_read + 100.0% [59] amd64_syscall + +11.86% [14] soreceive_generic @ /boot/kernel/kernel + 100.0% [14] soreceive + 100.0% [14] dofileread + 100.0% [14] sys_read + 100.0% [14] amd64_syscall + +11.86% [14] acpi_timer_get_timecount @ /boot/kernel/kernel + 85.71% [12] nanouptime + 100.0% [12] kern_clock_gettime + 100.0% [12] sys_clock_gettime + 100.0% [12] amd64_syscall + 14.29% [2] binuptime + 100.0% [2] cpu_idleclock + 100.0% [2] cpu_idle + 100.0% [2] sched_idletd + 100.0% [2] fork_exit + +03.39% [4] uma_zfree_arg @ /boot/kernel/kernel + 100.0% [4] mb_free_ext + 100.0% [4] m_free + 100.0% [4] soreceive_generic + 100.0% [4] soreceive + 100.0% [4] dofileread + 100.0% [4] sys_read + 100.0% [4] amd64_syscall + +01.69% [2] 0xb768a @ /lib/libc.so.7 + 100.0% [2] cJSON_Version @ /usr/local/lib/libiperf.so.0.0.0 + 100.0% [2] 0x202238 @ /usr/local/bin/iperf3 + 100.0% [2] 0x20210f + 100.0% [2] 0x201ee0 + +01.69% [2] tcp_output @ /boot/kernel/kernel + 100.0% [2] tcp_usr_rcvd + 100.0% [2] soreceive_generic + 100.0% [2] soreceive + 100.0% [2] dofileread + 100.0% [2] sys_read + 100.0% [2] amd64_syscall + +01.69% [2] uiomove_faultflag @ /boot/kernel/kernel + 100.0% [2] soreceive_generic + 100.0% [2] soreceive + 100.0% [2] dofileread + 100.0% [2] sys_read + 100.0% [2] amd64_syscall + +01.69% [2] Xfast_syscall @ /boot/kernel/kernel + +01.69% [2] pmap_kextract @ /boot/kernel/kernel + 100.0% [2] uma_zfree_arg + 100.0% [2] mb_free_ext + 100.0% [2] m_free + 100.0% [2] soreceive_generic + 100.0% [2] soreceive + 100.0% [2] dofileread + 100.0% [2] sys_read + 100.0% [2] amd64_syscall + +00.85% [1] virtqueue_dequeue @ /boot/kernel/kernel + 100.0% [1] vtnet_rxq_eof + 100.0% [1] vtnet_rx_vq_process + 100.0% [1] ithread_loop + 100.0% [1] fork_exit + +00.85% [1] _cv_timedwait_sig_sbt @ /boot/kernel/kernel + 100.0% [1] seltdwait + 100.0% [1] kern_select + 100.0% [1] sys_select + 100.0% [1] amd64_syscall + +00.85% [1] vtpci_legacy_notify_vq @ /boot/kernel/kernel + 100.0% [1] virtqueue_notify + 100.0% [1] vtnet_txq_notify + 100.0% [1] vtnet_txq_mq_start_locked + 100.0% [1] vtnet_txq_mq_start + 100.0% [1] ether_output_frame + 100.0% [1] ether_output + 100.0% [1] ip_output_send + 100.0% [1] ip_output + 100.0% [1] tcp_output + 100.0% [1] tcp_do_segment + 100.0% [1] tcp_input_with_port + 100.0% [1] tcp_input + 100.0% [1] ip_input + 100.0% [1] netisr_dispatch_src + 100.0% [1] ether_demux + 100.0% [1] ether_nh_input + 100.0% [1] netisr_dispatch_src + 100.0% [1] ether_input + 100.0% [1] vtnet_rxq_eof + 100.0% [1] vtnet_rx_vq_process + 100.0% [1] ithread_loop + 100.0% [1] fork_exit + +00.85% [1] acpi_cpu_c1 @ /boot/kernel/kernel + 100.0% [1] acpi_cpu_idle + 100.0% [1] cpu_idle_acpi + 100.0% [1] cpu_idle + 100.0% [1] sched_idletd + 100.0% [1] fork_exit + +00.85% [1] kern_select @ /boot/kernel/kernel + 100.0% [1] sys_select + 100.0% [1] amd64_syscall + +00.85% [1] sbfree @ /boot/kernel/kernel + 100.0% [1] soreceive_generic + 100.0% [1] soreceive + 100.0% [1] dofileread + 100.0% [1] sys_read + 100.0% [1] amd64_syscall + +00.85% [1] fget_only_user @ /boot/kernel/kernel + 100.0% [1] kern_select + 100.0% [1] sys_select + 100.0% [1] amd64_syscall + +00.85% [1] selfdfree @ /boot/kernel/kernel + 100.0% [1] kern_select + 100.0% [1] sys_select + 100.0% [1] amd64_syscall + +00.85% [1] PHYS_TO_VM_PAGE @ /boot/kernel/kernel + 100.0% [1] free + 100.0% [1] kern_select + 100.0% [1] sys_select + 100.0% [1] amd64_syscall + +00.85% [1] m_free @ /boot/kernel/kernel + 100.0% [1] soreceive_generic + 100.0% [1] soreceive + 100.0% [1] dofileread + 100.0% [1] sys_read + 100.0% [1] amd64_syscall + +00.85% [1] tcp_usr_rcvd @ /boot/kernel/kernel + 100.0% [1] soreceive_generic + 100.0% [1] soreceive + 100.0% [1] dofileread + 100.0% [1] sys_read + 100.0% [1] amd64_syscall + +00.85% [1] 0xb44f1 @ /lib/libc.so.7 + 100.0% [1] cJSON_Version @ /usr/local/lib/libiperf.so.0.0.0 + 100.0% [1] 0x202238 @ /usr/local/bin/iperf3 + 100.0% [1] 0x20210f + 100.0% [1] 0x201ee0 + +00.85% [1] maybe_yield @ /boot/kernel/kernel + 100.0% [1] uiomove_faultflag + 100.0% [1] soreceive_generic + 100.0% [1] soreceive + 100.0% [1] dofileread + 100.0% [1] sys_read + 100.0% [1] amd64_syscall + +00.85% [1] spinlock_exit @ /boot/kernel/kernel + 100.0% [1] cpu_idleclock + 100.0% [1] cpu_idle + 100.0% [1] sched_idletd + 100.0% [1] fork_exit + +00.85% [1] 0xf126 @ /lib/libthr.so.3 + 100.0% [1] cJSON_Version @ /usr/local/lib/libiperf.so.0.0.0 + 100.0% [1] 0x202238 @ /usr/local/bin/iperf3 + 100.0% [1] 0x20210f + 100.0% [1] 0x201ee0 + +00.85% [1] mb_free_ext @ /boot/kernel/kernel + 100.0% [1] m_free + 100.0% [1] soreceive_generic + 100.0% [1] soreceive + 100.0% [1] dofileread + 100.0% [1] sys_read + 100.0% [1] amd64_syscall + +00.85% [1] sopoll_generic @ /boot/kernel/kernel + 100.0% [1] kern_select + 100.0% [1] sys_select + 100.0% [1] amd64_syscall + diff --git a/tests/data/collapse-pmc/large.txt.gz b/tests/data/collapse-pmc/large.txt.gz new file mode 100644 index 0000000000000000000000000000000000000000..fac94dc3ce8f3461ee624e8bafeb77c603c94a4f GIT binary patch literal 117871 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 Odwv6q6i*FLRTcm_y>o{E literal 0 HcmV?d00001 diff --git a/tests/data/collapse-pmc/shared.txt b/tests/data/collapse-pmc/shared.txt new file mode 100644 index 00000000..2e49dddf --- /dev/null +++ b/tests/data/collapse-pmc/shared.txt @@ -0,0 +1,39 @@ +@ CLOCK.HARD [302186 samples] + +01.17% [173] randomdev_encrypt @ /boot/kernel/kernel + 95.95% [166] random_fortuna_read + 100.0% [166] read_random_uio + 100.0% [166] devfs_read_f + 100.0% [166] kern_readv + 100.0% [166] sys_read + 100.0% [166] amd64_syscall + 04.05% [7] read_random_uio + 100.0% [7] devfs_read_f + 100.0% [7] kern_readv + 100.0% [7] sys_read + 100.0% [7] amd64_syscall + +00.40% [59] acpi_timer_get_timecount @ /boot/kernel/kernel + 84.75% [50] binuptime + 54.00% [27] kern_clock_nanosleep + 100.0% [27] sys_nanosleep + 100.0% [27] amd64_syscall + 34.00% [17] cpu_idleclock + 100.0% [17] cpu_idle + 100.0% [17] sched_idletd + 100.0% [17] fork_exit + 10.00% [5] kern_poll + 100.0% [5] sys_poll + 100.0% [5] amd64_syscall + 02.00% [1] g_io_deliver + 100.0% [1] md_kthread + 100.0% [1] fork_exit + 10.17% [6] microtime + 100.0% [6] sys_gettimeofday + 100.0% [6] amd64_syscall + 05.08% [3] nanouptime + 100.0% [3] kern_clock_gettime + 100.0% [3] do_wait + 100.0% [3] __umtx_op_wait_uint_private + 100.0% [3] amd64_syscall + diff --git a/tests/data/collapse-pmc/shared2.txt b/tests/data/collapse-pmc/shared2.txt new file mode 100644 index 00000000..04d71b80 --- /dev/null +++ b/tests/data/collapse-pmc/shared2.txt @@ -0,0 +1,26 @@ +@ CLOCK.HARD [302186 samples] + +00.31% [2] 0xf4ae3 @ /lib/libc.so.7 + 50.00% [1] 0x53c2f @ /usr/lib/libprivatessh.so.5 + 50.00% [1] 0x3b25deb @ /usr/bin/clang-cpp + 100.0% [1] 0x48c282e + 100.0% [1] 0x48c73c8 + 100.0% [1] 0x385448a + 100.0% [1] 0x35c1b3e + 100.0% [1] 0x3854a2a + 100.0% [1] 0x1c0cc27 + 100.0% [1] 0x21f4d45 + 100.0% [1] 0x250c163 + 100.0% [1] 0x2152576 + 100.0% [1] 0x20cbe89 + 100.0% [1] 0x21e869f + 100.0% [1] 0x18a79e4 + 100.0% [1] 0x18b457c + 100.0% [1] 0x1fc8c57 + 100.0% [1] 0x3ac91aa + 100.0% [1] 0x1fc843e + 100.0% [1] 0x1f9d548 + 100.0% [1] 0x1f9da7c + 100.0% [1] 0x1fb0b7c + 100.0% [1] 0x18b40bb + 100.0% [1] 0x18a70a0 diff --git a/tests/data/collapse-pmc/simple.txt b/tests/data/collapse-pmc/simple.txt new file mode 100644 index 00000000..dbe82252 --- /dev/null +++ b/tests/data/collapse-pmc/simple.txt @@ -0,0 +1,18 @@ +@ CLOCK.HARD [302186 samples] + +86.17% [260401] acpi_cpu_c1 @ /boot/kernel/kernel + 100.0% [260401] acpi_cpu_idle + 100.0% [260401] cpu_idle_acpi + 100.0% [260401] cpu_idle + 100.0% [260401] sched_idletd + 100.0% [260401] fork_exit + +00.55% [1676] aes_ecb_encrypt @ /boot/kernel/kernel + 100.0% [1676] rijndael_blockEncrypt + 100.0% [1676] random_fortuna_read + 100.0% [1676] read_random_uio + 100.0% [1676] devfs_read_f + 100.0% [1676] kern_readv + 100.0% [1676] sys_read + 100.0% [1676] amd64_syscall + From 7df9d10bf51ee06674303559c610a470d863c609 Mon Sep 17 00:00:00 2001 From: pbmtp Date: Thu, 17 Jun 2021 17:57:24 +0200 Subject: [PATCH 2/5] add guess test for pmc format. --- tests/collapse-guess.rs | 7 +++++++ tests/data/collapse-pmc/results/dd-collapsed.txt | 13 +++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 tests/data/collapse-pmc/results/dd-collapsed.txt diff --git a/tests/collapse-guess.rs b/tests/collapse-guess.rs index c545d525..5c50be8e 100644 --- a/tests/collapse-guess.rs +++ b/tests/collapse-guess.rs @@ -85,6 +85,13 @@ fn collapse_guess_vtune() { test_collapse_guess(test_file, result_file, false).unwrap() } +#[test] +fn collapse_guess_pmc() { + let test_file = "./tests/data/collapse-pmc/dd.txt"; + let result_file = "./tests/data/collapse-pmc/results/dd-collapsed.txt"; + test_collapse_guess(test_file, result_file, false).unwrap() +} + #[test] fn collapse_guess_unknown_format_should_log_error() { test_collapse_guess_logs( diff --git a/tests/data/collapse-pmc/results/dd-collapsed.txt b/tests/data/collapse-pmc/results/dd-collapsed.txt new file mode 100644 index 00000000..16aa4b37 --- /dev/null +++ b/tests/data/collapse-pmc/results/dd-collapsed.txt @@ -0,0 +1,13 @@ +0x2042e0;0xb768a 2 +amd64_syscall;sys_read;dofileread;devfs_read_f;read_random_uio;malloc;malloc_large;kmem_malloc_domainset;kmem_back_domain;pmap_enter;pmap_promote_pde;pmap_update_pde;spinlock_exit 4 +amd64_syscall;sys_read;dofileread;devfs_read_f;read_random_uio;malloc;malloc_large;kmem_malloc_domainset;kmem_back_domain;vm_page_alloc_domain_after;vm_radix_insert 3 +amd64_syscall;sys_read;dofileread;devfs_read_f;read_random_uio;malloc;malloc_large;kmem_malloc_domainset;kmem_back_domain;vm_page_alloc_domain_after;vm_reserv_alloc_page;vm_domain_allocate 1 +amd64_syscall;sys_read;dofileread;devfs_read_f;read_random_uio;random_fortuna_read;random_fortuna_genbytes;randomdev_keystream 283 +amd64_syscall;sys_read;dofileread;devfs_read_f;read_random_uio;uiomove_faultflag;copyout_nosmap_std 8 +amd64_syscall;sys_read;dofileread;devfs_read_f;read_random_uio;zfree 1 +amd64_syscall;sys_read;dofileread;devfs_read_f;read_random_uio;zfree;explicit_bzero;memset_std 7 +amd64_syscall;sys_read;dofileread;devfs_read_f;read_random_uio;zfree;kmem_free;_kmem_unback;pmap_remove;pmap_demote_pde_locked;pmap_update_pde;spinlock_exit 3 +amd64_syscall;sys_read;dofileread;devfs_read_f;read_random_uio;zfree;kmem_free;_kmem_unback;vm_page_free_toq;vm_page_free_prep 2 +amd64_syscall;sys_read;dofileread;devfs_read_f;read_random_uio;zfree;kmem_free;_kmem_unback;vm_page_free_toq;vm_page_free_prep;vm_reserv_free_page 2 +fork_exit;pmclog_loop;_sleep;sleepq_timedwait;spinlock_exit 1 +fork_exit;sched_idletd;cpu_idle;cpu_activeclock;spinlock_exit 3 From c7c4cc01384888667ba4ff2d953241444a65b5bc Mon Sep 17 00:00:00 2001 From: pbmtp Date: Thu, 17 Jun 2021 17:59:33 +0200 Subject: [PATCH 3/5] add test suite for pmc collapser. --- tests/collapse-pmc.rs | 184 ++++++++++++++++++ .../collapse-pmc/results/iperf3-collapsed.txt | 27 +++ .../collapse-pmc/results/shared-collapsed.txt | 8 + .../results/shared2-collapsed.txt | 2 + .../collapse-pmc/results/simple-collapsed.txt | 2 + .../weird-stack-line-bad-count.txt | 5 + .../weird-stack-line-bad-percent.txt | 5 + .../weird-stack-line-no-function-name.txt | 5 + 8 files changed, 238 insertions(+) create mode 100644 tests/collapse-pmc.rs create mode 100644 tests/data/collapse-pmc/results/iperf3-collapsed.txt create mode 100644 tests/data/collapse-pmc/results/shared-collapsed.txt create mode 100644 tests/data/collapse-pmc/results/shared2-collapsed.txt create mode 100644 tests/data/collapse-pmc/results/simple-collapsed.txt create mode 100644 tests/data/collapse-pmc/weird-stack-line-bad-count.txt create mode 100644 tests/data/collapse-pmc/weird-stack-line-bad-percent.txt create mode 100644 tests/data/collapse-pmc/weird-stack-line-no-function-name.txt diff --git a/tests/collapse-pmc.rs b/tests/collapse-pmc.rs new file mode 100644 index 00000000..91a00bde --- /dev/null +++ b/tests/collapse-pmc.rs @@ -0,0 +1,184 @@ +mod common; + +use std::fs::File; +use std::io::{self, BufReader, Cursor}; +use std::path::Path; +use std::process::{Command, Stdio}; + +use assert_cmd::cargo::CommandCargoExt; +use inferno::collapse::pmc::{Folder, Options}; +use log::Level; +use pretty_assertions::assert_eq; +use testing_logger::CapturedLog; + +fn test_collapse_pmc( + test_file: &str, + expected_file: &str, + options: Options, + strip_quotes: bool, +) -> io::Result<()> { + for &n in &[1, 2] { + let mut options = options.clone(); + options.nthreads = n; + common::test_collapse( + Folder::from(options), + test_file, + expected_file, + strip_quotes, + )?; + } + Ok(()) +} + +fn test_collapse_pmc_logs_with_options(input_file: &str, asserter: F, mut options: Options) +where + F: Fn(&Vec), +{ + // We must run log tests in a single thread to play nicely with `testing_logger`. + options.nthreads = 1; + common::test_collapse_logs(Folder::from(options), input_file, asserter); +} + +fn test_collapse_pmc_logs(input_file: &str, asserter: F) +where + F: Fn(&Vec), +{ + test_collapse_pmc_logs_with_options(input_file, asserter, Options::default()); +} + +// Create tests for test files in $dir. The test files are used as input +// and the results are compared to result files in the results sub directory. +// The test and result file names are derived from $name. +macro_rules! collapse_pmc_tests_inner { + ($($name:ident),*; $dir:expr; $results_dir:expr; $strip_prefix:expr, $strip_quotes:expr) => { + $( + #[test] + #[allow(non_snake_case)] + fn $name() { + let mut test_name = stringify!($name); + if test_name.starts_with($strip_prefix) { + test_name = &test_name[$strip_prefix.len()..]; + } + let test_file_stem = test_name.replace("_", "-"); + + let test_file = format!("{}.txt", test_file_stem); + let result_file = format!("{}-collapsed.txt", test_file_stem); + + let test_path = Path::new($dir); + let results_path = Path::new($results_dir); + + test_collapse_pmc( + test_path.join(test_file).to_str().unwrap(), + results_path.join(result_file).to_str().unwrap(), + Options::default(), + $strip_quotes + ).unwrap() + } + )* + } +} + +macro_rules! collapse_pmc_tests { + ($($name:ident),*) => { + collapse_pmc_tests_inner!($($name),*; "./tests/data/collapse-pmc"; "./tests/data/collapse-pmc/results"; "collapse_pmc_", false); + } +} + +collapse_pmc_tests! { + collapse_pmc_simple, + collapse_pmc_shared, + collapse_pmc_shared2, + collapse_pmc_dd, + collapse_pmc_iperf3 +} + +#[test] +fn collapse_pmc_should_warn_about_weird_input_lines_bad_percent() { + test_collapse_pmc_logs( + "./tests/data/collapse-pmc/weird-stack-line-bad-percent.txt", + |captured_logs| { + let nwarnings = captured_logs + .iter() + .filter(|log| { + log.body.starts_with("Weird stack line: ") && log.level == Level::Warn + }) + .count(); + assert_eq!( + nwarnings, 1, + "bad lines warning logged {} times, but should be logged exactly once", + nwarnings + ); + }, + ); +} + +#[test] +fn collapse_pmc_should_warn_about_weird_input_lines_bad_count() { + // bad count + test_collapse_pmc_logs( + "./tests/data/collapse-pmc/weird-stack-line-bad-count.txt", + |captured_logs| { + let nwarnings = captured_logs + .iter() + .filter(|log| { + log.body.starts_with("Weird stack line: ") && log.level == Level::Warn + }) + .count(); + assert_eq!( + nwarnings, 1, + "bad lines warning logged {} times, but should be logged exactly once", + nwarnings + ); + }, + ); +} + +#[test] +fn collapse_pmc_should_warn_about_weird_input_lines_no_function_name() { + // no funcname + test_collapse_pmc_logs( + "./tests/data/collapse-pmc/weird-stack-line-no-function-name.txt", + |captured_logs| { + let nwarnings = captured_logs + .iter() + .filter(|log| { + log.body.starts_with("Weird stack line: ") && log.level == Level::Warn + }) + .count(); + assert_eq!( + nwarnings, 1, + "bad lines warning logged {} times, but should be logged exactly once", + nwarnings + ); + }, + ); +} + +#[test] +fn collapse_pmc_cli() { + let input_file = "./tests/data/collapse-pmc/dd.txt"; + let expected_file = "./tests/data/collapse-pmc/results/dd-collapsed.txt"; + + // Test with file passed in + let output = Command::cargo_bin("inferno-collapse-pmc") + .unwrap() + .arg(input_file) + .output() + .expect("failed to execute process"); + let expected = BufReader::new(File::open(expected_file).unwrap()); + common::compare_results(Cursor::new(output.stdout), expected, expected_file, true); + + // Test with STDIN + let mut child = Command::cargo_bin("inferno-collapse-pmc") + .unwrap() + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn() + .expect("Failed to spawn child process"); + let mut input = BufReader::new(File::open(input_file).unwrap()); + let stdin = child.stdin.as_mut().expect("Failed to open stdin"); + 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()); + common::compare_results(Cursor::new(output.stdout), expected, expected_file, true); +} diff --git a/tests/data/collapse-pmc/results/iperf3-collapsed.txt b/tests/data/collapse-pmc/results/iperf3-collapsed.txt new file mode 100644 index 00000000..c0fe2730 --- /dev/null +++ b/tests/data/collapse-pmc/results/iperf3-collapsed.txt @@ -0,0 +1,27 @@ +0x201ee0;0x20210f;0x202238;cJSON_Version;0xb44f1 1 +0x201ee0;0x20210f;0x202238;cJSON_Version;0xb768a 2 +0x201ee0;0x20210f;0x202238;cJSON_Version;0xf126 1 +Xfast_syscall 2 +amd64_syscall;sys_clock_gettime;kern_clock_gettime;nanouptime;acpi_timer_get_timecount 12 +amd64_syscall;sys_read;dofileread;soreceive;soreceive_generic 14 +amd64_syscall;sys_read;dofileread;soreceive;soreceive_generic;m_free 1 +amd64_syscall;sys_read;dofileread;soreceive;soreceive_generic;m_free;mb_free_ext 1 +amd64_syscall;sys_read;dofileread;soreceive;soreceive_generic;m_free;mb_free_ext;uma_zfree_arg 4 +amd64_syscall;sys_read;dofileread;soreceive;soreceive_generic;m_free;mb_free_ext;uma_zfree_arg;pmap_kextract 2 +amd64_syscall;sys_read;dofileread;soreceive;soreceive_generic;sbfree 1 +amd64_syscall;sys_read;dofileread;soreceive;soreceive_generic;tcp_usr_rcvd 1 +amd64_syscall;sys_read;dofileread;soreceive;soreceive_generic;tcp_usr_rcvd;tcp_output 2 +amd64_syscall;sys_read;dofileread;soreceive;soreceive_generic;uiomove_faultflag 2 +amd64_syscall;sys_read;dofileread;soreceive;soreceive_generic;uiomove_faultflag;copyout_nosmap_std 59 +amd64_syscall;sys_read;dofileread;soreceive;soreceive_generic;uiomove_faultflag;maybe_yield 1 +amd64_syscall;sys_select;kern_select 1 +amd64_syscall;sys_select;kern_select;fget_only_user 1 +amd64_syscall;sys_select;kern_select;free;PHYS_TO_VM_PAGE 1 +amd64_syscall;sys_select;kern_select;selfdfree 1 +amd64_syscall;sys_select;kern_select;seltdwait;_cv_timedwait_sig_sbt 1 +amd64_syscall;sys_select;kern_select;sopoll_generic 1 +fork_exit;ithread_loop;vtnet_rx_vq_process;vtnet_rxq_eof;ether_input;netisr_dispatch_src;ether_nh_input;ether_demux;netisr_dispatch_src;ip_input;tcp_input;tcp_input_with_port;tcp_do_segment;tcp_output;ip_output;ip_output_send;ether_output;ether_output_frame;vtnet_txq_mq_start;vtnet_txq_mq_start_locked;vtnet_txq_notify;virtqueue_notify;vtpci_legacy_notify_vq 1 +fork_exit;ithread_loop;vtnet_rx_vq_process;vtnet_rxq_eof;virtqueue_dequeue 1 +fork_exit;sched_idletd;cpu_idle;cpu_idle_acpi;acpi_cpu_idle;acpi_cpu_c1 1 +fork_exit;sched_idletd;cpu_idle;cpu_idleclock;binuptime;acpi_timer_get_timecount 2 +fork_exit;sched_idletd;cpu_idle;cpu_idleclock;spinlock_exit 1 diff --git a/tests/data/collapse-pmc/results/shared-collapsed.txt b/tests/data/collapse-pmc/results/shared-collapsed.txt new file mode 100644 index 00000000..72edfb4a --- /dev/null +++ b/tests/data/collapse-pmc/results/shared-collapsed.txt @@ -0,0 +1,8 @@ +amd64_syscall;__umtx_op_wait_uint_private;do_wait;kern_clock_gettime;nanouptime;acpi_timer_get_timecount 3 +amd64_syscall;sys_gettimeofday;microtime;acpi_timer_get_timecount 6 +amd64_syscall;sys_nanosleep;kern_clock_nanosleep;binuptime;acpi_timer_get_timecount 27 +amd64_syscall;sys_poll;kern_poll;binuptime;acpi_timer_get_timecount 5 +amd64_syscall;sys_read;kern_readv;devfs_read_f;read_random_uio;random_fortuna_read;randomdev_encrypt 166 +amd64_syscall;sys_read;kern_readv;devfs_read_f;read_random_uio;randomdev_encrypt 7 +fork_exit;md_kthread;g_io_deliver;binuptime;acpi_timer_get_timecount 1 +fork_exit;sched_idletd;cpu_idle;cpu_idleclock;binuptime;acpi_timer_get_timecount 17 diff --git a/tests/data/collapse-pmc/results/shared2-collapsed.txt b/tests/data/collapse-pmc/results/shared2-collapsed.txt new file mode 100644 index 00000000..3d76dcb0 --- /dev/null +++ b/tests/data/collapse-pmc/results/shared2-collapsed.txt @@ -0,0 +1,2 @@ +0x18a70a0;0x18b40bb;0x1fb0b7c;0x1f9da7c;0x1f9d548;0x1fc843e;0x3ac91aa;0x1fc8c57;0x18b457c;0x18a79e4;0x21e869f;0x20cbe89;0x2152576;0x250c163;0x21f4d45;0x1c0cc27;0x3854a2a;0x35c1b3e;0x385448a;0x48c73c8;0x48c282e;0x3b25deb;0xf4ae3 1 +0x53c2f;0xf4ae3 1 diff --git a/tests/data/collapse-pmc/results/simple-collapsed.txt b/tests/data/collapse-pmc/results/simple-collapsed.txt new file mode 100644 index 00000000..99eb7c7e --- /dev/null +++ b/tests/data/collapse-pmc/results/simple-collapsed.txt @@ -0,0 +1,2 @@ +amd64_syscall;sys_read;kern_readv;devfs_read_f;read_random_uio;random_fortuna_read;rijndael_blockEncrypt;aes_ecb_encrypt 1676 +fork_exit;sched_idletd;cpu_idle;cpu_idle_acpi;acpi_cpu_idle;acpi_cpu_c1 260401 diff --git a/tests/data/collapse-pmc/weird-stack-line-bad-count.txt b/tests/data/collapse-pmc/weird-stack-line-bad-count.txt new file mode 100644 index 00000000..d594b748 --- /dev/null +++ b/tests/data/collapse-pmc/weird-stack-line-bad-count.txt @@ -0,0 +1,5 @@ +@ CLOCK.HARD [302186 samples] + +86.17% [260401] acpi_cpu_c1 @ /boot/kernel/kernel + 100.0% [] acpi_cpu_idle + diff --git a/tests/data/collapse-pmc/weird-stack-line-bad-percent.txt b/tests/data/collapse-pmc/weird-stack-line-bad-percent.txt new file mode 100644 index 00000000..ce24a7b7 --- /dev/null +++ b/tests/data/collapse-pmc/weird-stack-line-bad-percent.txt @@ -0,0 +1,5 @@ +@ CLOCK.HARD [302186 samples] + +86.17% [260401] acpi_cpu_c1 @ /boot/kernel/kernel + % [260401] acpi_cpu_idle + diff --git a/tests/data/collapse-pmc/weird-stack-line-no-function-name.txt b/tests/data/collapse-pmc/weird-stack-line-no-function-name.txt new file mode 100644 index 00000000..e63e7ed8 --- /dev/null +++ b/tests/data/collapse-pmc/weird-stack-line-no-function-name.txt @@ -0,0 +1,5 @@ +@ CLOCK.HARD [302186 samples] + +86.17% [260401] acpi_cpu_c1 @ /boot/kernel/kernel + 100.0% [260401] + From 4d052760a24ff95f866bf1e041bab51a694c0169 Mon Sep 17 00:00:00 2001 From: pbmtp Date: Thu, 17 Jun 2021 18:07:41 +0200 Subject: [PATCH 4/5] fix issues from clippy. --- src/collapse/pmc.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/collapse/pmc.rs b/src/collapse/pmc.rs index c542bbe6..cd27ec48 100644 --- a/src/collapse/pmc.rs +++ b/src/collapse/pmc.rs @@ -249,7 +249,7 @@ impl Folder { // 100.0% [1318] sched_idletd // 100.0% [1318] fork_exit fn on_stack_line(&mut self, line: &str, occurrences: &mut Occurrences) { - let parts = Self::stack_line_parts(&line); + let parts = Self::stack_line_parts(line); match parts { Some((indent, _, count, function)) => { // detect shared stacks, i.e. stacks that share some elements @@ -289,7 +289,7 @@ impl Folder { } else { first = false; } - stack_str.push_str(&e); + stack_str.push_str(e); } // count it! From 9c1945c94c3e03452842cae99bc2345682968696 Mon Sep 17 00:00:00 2001 From: pbmtp Date: Thu, 17 Jun 2021 18:30:38 +0200 Subject: [PATCH 5/5] cargo fmt. --- benches/collapse.rs | 2 +- src/collapse/guess.rs | 2 +- src/collapse/pmc.rs | 27 +++++++++++++++------------ 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/benches/collapse.rs b/benches/collapse.rs index 7b99ba84..60f00b8c 100644 --- a/benches/collapse.rs +++ b/benches/collapse.rs @@ -2,7 +2,7 @@ use std::fs::File; use std::io::{self, Read}; use criterion::*; -use inferno::collapse::{dtrace, perf, sample, pmc, Collapse}; +use inferno::collapse::{dtrace, perf, pmc, sample, Collapse}; use lazy_static::lazy_static; use libflate::gzip::Decoder; diff --git a/src/collapse/guess.rs b/src/collapse/guess.rs index 60af53c1..06981c63 100644 --- a/src/collapse/guess.rs +++ b/src/collapse/guess.rs @@ -3,7 +3,7 @@ use std::io::{self, Cursor}; use log::{error, info}; -use crate::collapse::{self, dtrace, perf, sample, vtune, pmc, Collapse}; +use crate::collapse::{self, dtrace, perf, pmc, sample, vtune, Collapse}; const LINES_PER_ITERATION: usize = 10; diff --git a/src/collapse/pmc.rs b/src/collapse/pmc.rs index cd27ec48..44fff835 100644 --- a/src/collapse/pmc.rs +++ b/src/collapse/pmc.rs @@ -35,7 +35,6 @@ impl Default for Options { /// `pmc::Folder::from(options)`. pub struct Folder { // State... - /// The number of stacks per job to send to the threadpool. nstacks_per_job: usize, @@ -277,9 +276,8 @@ impl Folder { // 100.0% [1] 0x48c73c8 if self.indent.is_some() && indent <= self.indent.unwrap_or(0) { // allocate a string that is long enough to hold the entire stack string - let mut stack_str = String::with_capacity( - self.stack.iter().fold(0, |a, s| a + s.len() + 1), - ); + let mut stack_str = + String::with_capacity(self.stack.iter().fold(0, |a, s| a + s.len() + 1)); // add the stack entries let mut first = true; @@ -294,10 +292,13 @@ impl Folder { // count it! assert!(self.count.is_some()); - occurrences.insert_or_add(stack_str, self.count.expect("count not found on previous line")); + occurrences.insert_or_add( + stack_str, + self.count.expect("count not found on previous line"), + ); // pop as many element as needed to prepare for the next shared stack - self.stack.drain(.. self.stack.len() - indent); + self.stack.drain(..self.stack.len() - indent); } self.indent = Some(indent); @@ -307,10 +308,10 @@ impl Folder { // TODO filter raw addresses // TODO demangle C++ / Rust symbols self.stack.push_front(function.to_string()); - }, + } None => { logging::weird_stack_line(line); - }, + } } } @@ -318,9 +319,8 @@ impl Folder { // end of stack, so emit stack entry if !self.stack.is_empty() { // allocate a string that is long enough to hold the entire stack string - let mut stack_str = String::with_capacity( - self.stack.iter().fold(0, |a, s| a + s.len() + 1), - ); + let mut stack_str = + String::with_capacity(self.stack.iter().fold(0, |a, s| a + s.len() + 1)); // add the stack entries (if any) let mut first = true; @@ -335,7 +335,10 @@ impl Folder { // count it! assert!(self.count.is_some()); - occurrences.insert_or_add(stack_str, self.count.expect("count not found on previous line")); + occurrences.insert_or_add( + stack_str, + self.count.expect("count not found on previous line"), + ); } // reset for next stack