diff --git a/CHANGELOG.md b/CHANGELOG.md index caecb8a0..a2d4b1e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added + - Support kernel annotations for versioned vmlinux and kernel modules in collapse-perf. [#182](https://github.com/jonhoo/inferno/pull/182) ### Changed diff --git a/src/collapse/matcher.rs b/src/collapse/matcher.rs new file mode 100644 index 00000000..031e60c3 --- /dev/null +++ b/src/collapse/matcher.rs @@ -0,0 +1,100 @@ +// Detects vmlinux in stack, with version or without. +// +// Examples: +// +// ffffffffb94000e0 __softirqentry_text_start+0xe0 (/usr/lib/debug/boot/vmlinux-5.4.14-cloudflare-2020.1.11) +// 8c3453 tcp_sendmsg (/lib/modules/4.3.0-rc1-virtual/build/vmlinux) +// 7d8 ipv4_conntrack_local+0x7f8f80b8 ([nf_conntrack_ipv4]) +// +#[inline] +pub fn is_vmlinux(s: &str) -> bool { + if let Some(vm) = s.rfind("vmlinux") { + s[vm..].chars().all(|c| { + c.is_ascii_alphanumeric() + || match c { + '-' | '.' | '_' => true, + _ => false, + } + }) + } else { + false + } +} + +// Detect kernel from module name, module file or from vmlinux +#[inline] +pub fn is_kernel(s: &str) -> bool { + (s.starts_with('[') || s.ends_with(".ko") || is_vmlinux(s)) && s != "[unknown]" +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn is_vmlinux_true() { + assert!(is_vmlinux("vmlinux")); + assert!(is_vmlinux("vmlinux-5")); + assert!(is_vmlinux("vmlinux-54")); + assert!(is_vmlinux("vmlinux_54")); + assert!(is_vmlinux("vmlinux-vmlinux")); + assert!(is_vmlinux("vmlinux-5.4.14")); + assert!(is_vmlinux("vmlinux-54-2020")); + assert!(is_vmlinux("vmlinux-cloudflare")); + assert!(is_vmlinux("vmlinux_cloudflare")); + assert!(is_vmlinux("vmlinux-cloudflare-2020.1.11")); + assert!(is_vmlinux("vmlinux-5.4.14-cloudflare-2020.1.11")); + assert!(is_vmlinux("/usr/lib/debug/boot/vmlinux")); + assert!(is_vmlinux( + "/usr/lib/debug/boot/vmlinux-5.4.14-cloudflare-2020.1.11" + )); + } + + #[test] + fn is_vmlinux_false() { + assert!(!is_vmlinux("vmlinux/")); + assert!(!is_vmlinux("vmlinux ")); + assert!(!is_vmlinux("vmlinux+5")); + assert!(!is_vmlinux("vmlinux,54")); + assert!(!is_vmlinux("vmlinux\\5.4.14")); + assert!(!is_vmlinux("vmlinux-Тест")); + assert!(!is_vmlinux("vmlinux-cloudflare ")); + assert!(!is_vmlinux("vmlinux-5.4.14-cloudflare-2020.1.11)")); + assert!(!is_vmlinux("/usr/lib/debug/boot/vmlinu")); + assert!(!is_vmlinux( + "/usr/lib/debug/boot/vmlinu-5.4.14-cloudflare-2020.1.11" + )); + } + + #[test] + fn is_kernel_true() { + assert!(is_kernel("[")); + assert!(is_kernel("[vmlinux")); + assert!(is_kernel("[test")); + assert!(is_kernel("[test]")); + assert!(is_kernel(".ko")); + assert!(is_kernel("module.ko")); + assert!(is_kernel("vmlinux.ko")); + assert!(is_kernel("vmlinux")); + assert!(is_kernel(" [vmlinux")); + assert!(is_kernel("vmlinux-5.4.14-cloudflare-2020.1.11")); + assert!(is_kernel("vmlinux-5.4.14-cloudflare-2020.1.11")); + assert!(is_kernel( + "/usr/lib/debug/boot/vmlinux-5.4.14-cloudflare-2020.1.11" + )); + } + + #[test] + fn is_kernel_false() { + assert!(!is_kernel("[unknown]")); + assert!(!is_kernel(" [")); + assert!(!is_kernel(".ko ")); + assert!(!is_kernel(" [.ko ")); + assert!(!is_kernel("vmlinux-cloudflare ")); + assert!(!is_kernel("vmlinux-5.4.14-cloudflare-2020.1.11)")); + assert!(!is_kernel("/usr/lib/debug/boot/vmlinu")); + assert!(!is_kernel( + "/usr/lib/debug/boot/vmlinu-5.4.14-cloudflare-2020.1.11" + )); + } +} diff --git a/src/collapse/mod.rs b/src/collapse/mod.rs index c5d1e439..d0e8a4eb 100644 --- a/src/collapse/mod.rs +++ b/src/collapse/mod.rs @@ -18,6 +18,9 @@ pub mod guess; /// [crate-level documentation]: ../../index.html pub mod perf; +/// Internal string match helper functions for perf +pub(crate) mod matcher; + /// Stack collapsing for the output of [`sample`](https://gist.github.com/loderunner/36724cc9ee8db66db305#profiling-with-sample) on macOS. /// /// See the [crate-level documentation] for details. diff --git a/src/collapse/perf.rs b/src/collapse/perf.rs index 02c1a918..371f78fb 100644 --- a/src/collapse/perf.rs +++ b/src/collapse/perf.rs @@ -2,6 +2,7 @@ use std::collections::VecDeque; use std::io::{self, BufRead}; use crate::collapse::common::{self, CollapsePrivate, Occurrences}; +use crate::collapse::matcher::is_kernel; const TIDY_GENERIC: bool = true; const TIDY_JAVA: bool = true; @@ -514,10 +515,7 @@ impl Folder { // 7f722d142778 Ljava/io/PrintStream;::print (/tmp/perf-19982.map) if !self.cache_line.is_empty() { func.push_str("_[i]"); // inlined - } else if self.opt.annotate_kernel - && (module.starts_with('[') || module.ends_with("vmlinux")) - && module != "[unknown]" - { + } else if self.opt.annotate_kernel && is_kernel(module) { func.push_str("_[k]"); // kernel } else if self.opt.annotate_jit && module.starts_with("/tmp/perf-") diff --git a/tests/collapse-perf.rs b/tests/collapse-perf.rs index dc2c2e03..4841b077 100644 --- a/tests/collapse-perf.rs +++ b/tests/collapse-perf.rs @@ -232,7 +232,8 @@ collapse_perf_tests! { collapse_perf_single_line_stacks, collapse_perf_single_event, collapse_perf_go_stacks, - collapse_perf_java_inline + collapse_perf_java_inline, + collapse_perf_versioned_vmlinux__kernel } #[test] diff --git a/tests/data/collapse-perf/results/versioned-vmlinux-collapsed-kernel.txt b/tests/data/collapse-perf/results/versioned-vmlinux-collapsed-kernel.txt new file mode 100644 index 00000000..77d5431f --- /dev/null +++ b/tests/data/collapse-perf/results/versioned-vmlinux-collapsed-kernel.txt @@ -0,0 +1 @@ +swapper;[vmlinux-5.4.14-cloudflare-2020.1.11]_[k];start_secondary_[k];cpu_startup_entry_[k];do_idle_[k];cpuidle_enter_[k];cpuidle_enter_state_[k];common_interrupt_[k];do_IRQ_[k];irq_exit_[k];__softirqentry_text_start_[k];net_rx_action_[k];mlx5e_napi_poll_[k];mlx5e_poll_rx_cq_[k];mlx5e_handle_rx_cqe_[k];mlx5e_skb_from_cqe_linear_[k];mlx5e_xdp_handle_[k];bpf_prog_2b956549c660136a_uni_l4lb 1 diff --git a/tests/data/collapse-perf/versioned-vmlinux.txt b/tests/data/collapse-perf/versioned-vmlinux.txt new file mode 100644 index 00000000..9f4b2946 --- /dev/null +++ b/tests/data/collapse-perf/versioned-vmlinux.txt @@ -0,0 +1,18 @@ +swapper 0 [012] 2281339.604067: 20834821 cycles: + ffffffffc09ace93 bpf_prog_2b956549c660136a_uni_l4lb+0xb80 (bpf_prog_2b956549c660136a_uni_l4lb) + ffffffffc087cbc9 mlx5e_xdp_handle+0xa9 (/lib/modules/5.4.14-cloudflare-2020.1.11/kernel/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.ko) + ffffffffc0878d87 mlx5e_skb_from_cqe_linear+0xc7 (/lib/modules/5.4.14-cloudflare-2020.1.11/kernel/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.ko) + ffffffffc087a254 mlx5e_handle_rx_cqe+0x64 (/lib/modules/5.4.14-cloudflare-2020.1.11/kernel/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.ko) + ffffffffc087bb48 mlx5e_poll_rx_cq+0x808 (/lib/modules/5.4.14-cloudflare-2020.1.11/kernel/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.ko) + ffffffffc087beee mlx5e_napi_poll+0xde (/lib/modules/5.4.14-cloudflare-2020.1.11/kernel/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.ko) + ffffffffb8f03eaa net_rx_action+0x13a (/usr/lib/debug/boot/vmlinux-5.4.14-cloudflare-2020.1.11) + ffffffffb94000e0 __softirqentry_text_start+0xe0 (/usr/lib/debug/boot/vmlinux-5.4.14-cloudflare-2020.1.11) + ffffffffb886c8c0 irq_exit+0xa0 (/usr/lib/debug/boot/vmlinux-5.4.14-cloudflare-2020.1.11) + ffffffffb9201908 do_IRQ+0x58 (/usr/lib/debug/boot/vmlinux-5.4.14-cloudflare-2020.1.11) + ffffffffb9200a0f common_interrupt+0xf (/usr/lib/debug/boot/vmlinux-5.4.14-cloudflare-2020.1.11) + ffffffffb8ebc022 cpuidle_enter_state+0xb2 (/usr/lib/debug/boot/vmlinux-5.4.14-cloudflare-2020.1.11) + ffffffffb8ebc3c9 cpuidle_enter+0x29 (/usr/lib/debug/boot/vmlinux-5.4.14-cloudflare-2020.1.11) + ffffffffb88960f8 do_idle+0x1b8 (/usr/lib/debug/boot/vmlinux-5.4.14-cloudflare-2020.1.11) + ffffffffb88962c9 cpu_startup_entry+0x19 (/usr/lib/debug/boot/vmlinux-5.4.14-cloudflare-2020.1.11) + ffffffffb8841383 start_secondary+0x143 (/usr/lib/debug/boot/vmlinux-5.4.14-cloudflare-2020.1.11) + ffffffffb88000d4 [unknown] (/usr/lib/debug/boot/vmlinux-5.4.14-cloudflare-2020.1.11)