From 9a863f235c7beb5201e05f7023f25fbb40d5776b Mon Sep 17 00:00:00 2001 From: Andreas Jonson Date: Tue, 5 Nov 2019 20:35:27 +0100 Subject: [PATCH] add new tool flamegraph add crate tools_lib to reuse functionality between tools. --- CHANGELOG.md | 5 ++ Cargo.toml | 2 + README.md | 6 +++ flamegraph/Cargo.toml | 12 +++++ flamegraph/README.md | 17 ++++++ flamegraph/src/main.rs | 53 +++++++++++++++++++ stack_collapse/Cargo.toml | 1 + stack_collapse/src/main.rs | 4 +- tools_lib/Cargo.toml | 9 ++++ tools_lib/src/lib.rs | 1 + .../src/stack_collapse.rs | 0 11 files changed, 107 insertions(+), 3 deletions(-) create mode 100644 flamegraph/Cargo.toml create mode 100644 flamegraph/README.md create mode 100644 flamegraph/src/main.rs create mode 100644 tools_lib/Cargo.toml create mode 100644 tools_lib/src/lib.rs rename {stack_collapse => tools_lib}/src/stack_collapse.rs (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index f101e10..6d0baff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## Unreleased +### Added +- `flamegraph`: new tool that uses the `inferno` crate to generate flamegraph svg files ([GH-73]) + ## [0.4.0] - 2019-10-24 ### Added - `measureme`: Added RAII-based API for recording events ([GH-70]) @@ -37,3 +41,4 @@ [GH-59]: https://github.com/rust-lang/measureme/pull/59 [GH-60]: https://github.com/rust-lang/measureme/pull/60 [GH-70]: https://github.com/rust-lang/measureme/pull/70 +[GH-73]: https://github.com/rust-lang/measureme/pull/73 diff --git a/Cargo.toml b/Cargo.toml index 0935db1..c192155 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,4 +6,6 @@ members = [ "mmview", "stack_collapse", "summarize", + "tools_lib", + "flamegraph", ] diff --git a/README.md b/README.md index 80e6647..cd24417 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,12 @@ It contains two main modes: [Learn more](./stack_collapse/README.md) +### flamegraph + +`flamegraph` reads `measureme` profiling data and outputs [Flame Graph](https://github.com/brendangregg/FlameGraph). + +[Learn more](./flamegraph/README.md) + ### crox `crox` turns `measureme` profiling data into files that can be visualized by the Chromium performance tools. diff --git a/flamegraph/Cargo.toml b/flamegraph/Cargo.toml new file mode 100644 index 0000000..2307853 --- /dev/null +++ b/flamegraph/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "flamegraph" +version = "0.1.0" +authors = ["Wesley Wiser ", "Michael Woerister "] +edition = "2018" +license = "MIT OR Apache-2.0" + +[dependencies] +measureme = { path = "../measureme" } +tools_lib = { path = "../tools_lib" } +structopt = "0.2" +inferno = { version="0.9.1", default-features = false } diff --git a/flamegraph/README.md b/flamegraph/README.md new file mode 100644 index 0000000..4db3e30 --- /dev/null +++ b/flamegraph/README.md @@ -0,0 +1,17 @@ +# flamegraph + +flamegraph is a tool to produce [Flame Graph](https://github.com/brendangregg/FlameGraph) from `measureme` data. + +## Example + +```bash +$ git clone https://github.com/rust-lang/regex.git + +$ cd regex + +$ cargo rustc -- -Z self-profile + +$ flamegraph pid-{pid} + +$ open rustc.svg +``` diff --git a/flamegraph/src/main.rs b/flamegraph/src/main.rs new file mode 100644 index 0000000..8bf7c6f --- /dev/null +++ b/flamegraph/src/main.rs @@ -0,0 +1,53 @@ +use std::error::Error; +use std::fs::File; +use std::io::BufWriter; +use std::path::PathBuf; +use std::time::Duration; + +use measureme::ProfilingData; + +use structopt::StructOpt; + +use tools_lib::stack_collapse::collapse_stacks; + +use inferno::flamegraph::{from_lines, Options as FlamegraphOptions}; + +#[derive(StructOpt, Debug)] +struct Opt { + file_prefix: PathBuf, + + /// The sampling interval in milliseconds + #[structopt(short = "i", long = "interval", default_value = "1")] + interval: u64, +} + +fn main() -> Result<(), Box> { + let opt = Opt::from_args(); + + let profiling_data = ProfilingData::new(&opt.file_prefix)?; + + let first_event_time = { + let current_time = profiling_data.iter().next().unwrap().timestamp; + current_time + Duration::from_millis(opt.interval) + }; + + let recorded_stacks = collapse_stacks(profiling_data.iter(), first_event_time, opt.interval) + .iter() + .map(|(unique_stack, count)| format!("{} {}", unique_stack, count)) + .collect::>(); + + let file = BufWriter::new(File::create("rustc.svg")?); + let mut flamegraph_options = FlamegraphOptions::default(); + + from_lines( + &mut flamegraph_options, + recorded_stacks.iter().map(|s| s.as_ref()), + file, + ) + .expect( + "unable to generate a flamegraph \ + from the collapsed stack data", + ); + + Ok(()) +} diff --git a/stack_collapse/Cargo.toml b/stack_collapse/Cargo.toml index 57b1d98..8bb1be4 100644 --- a/stack_collapse/Cargo.toml +++ b/stack_collapse/Cargo.toml @@ -7,4 +7,5 @@ license = "MIT OR Apache-2.0" [dependencies] measureme = { path = "../measureme" } +tools_lib = { path = "../tools_lib" } structopt = "0.2" diff --git a/stack_collapse/src/main.rs b/stack_collapse/src/main.rs index 163f5d2..e6a2b50 100644 --- a/stack_collapse/src/main.rs +++ b/stack_collapse/src/main.rs @@ -8,9 +8,7 @@ use measureme::ProfilingData; use structopt::StructOpt; -mod stack_collapse; - -use stack_collapse::collapse_stacks; +use tools_lib::stack_collapse::collapse_stacks; #[derive(StructOpt, Debug)] struct Opt { diff --git a/tools_lib/Cargo.toml b/tools_lib/Cargo.toml new file mode 100644 index 0000000..310ccb6 --- /dev/null +++ b/tools_lib/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "tools_lib" +version = "0.1.0" +authors = ["Wesley Wiser ", "Michael Woerister "] +edition = "2018" +license = "MIT OR Apache-2.0" + +[dependencies] +measureme = { path = "../measureme" } \ No newline at end of file diff --git a/tools_lib/src/lib.rs b/tools_lib/src/lib.rs new file mode 100644 index 0000000..45e2ae6 --- /dev/null +++ b/tools_lib/src/lib.rs @@ -0,0 +1 @@ +pub mod stack_collapse; diff --git a/stack_collapse/src/stack_collapse.rs b/tools_lib/src/stack_collapse.rs similarity index 100% rename from stack_collapse/src/stack_collapse.rs rename to tools_lib/src/stack_collapse.rs