Skip to content

Commit 9d5d1e8

Browse files
authored
Merge pull request #73 from andjo403/inferno
use Inferno to generate flamegraphs
2 parents 4b9ec6e + 9a863f2 commit 9d5d1e8

File tree

11 files changed

+107
-3
lines changed

11 files changed

+107
-3
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
## Unreleased
4+
### Added
5+
- `flamegraph`: new tool that uses the `inferno` crate to generate flamegraph svg files ([GH-73])
6+
37
## [0.4.0] - 2019-10-24
48
### Added
59
- `measureme`: Added RAII-based API for recording events ([GH-70])
@@ -37,3 +41,4 @@
3741
[GH-59]: https://github.com/rust-lang/measureme/pull/59
3842
[GH-60]: https://github.com/rust-lang/measureme/pull/60
3943
[GH-70]: https://github.com/rust-lang/measureme/pull/70
44+
[GH-73]: https://github.com/rust-lang/measureme/pull/73

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,6 @@ members = [
66
"mmview",
77
"stack_collapse",
88
"summarize",
9+
"tools_lib",
10+
"flamegraph",
911
]

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ It contains two main modes:
2929

3030
[Learn more](./stack_collapse/README.md)
3131

32+
### flamegraph
33+
34+
`flamegraph` reads `measureme` profiling data and outputs [Flame Graph](https://github.com/brendangregg/FlameGraph).
35+
36+
[Learn more](./flamegraph/README.md)
37+
3238
### crox
3339

3440
`crox` turns `measureme` profiling data into files that can be visualized by the Chromium performance tools.

flamegraph/Cargo.toml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[package]
2+
name = "flamegraph"
3+
version = "0.1.0"
4+
authors = ["Wesley Wiser <[email protected]>", "Michael Woerister <michaelwoerister@posteo>"]
5+
edition = "2018"
6+
license = "MIT OR Apache-2.0"
7+
8+
[dependencies]
9+
measureme = { path = "../measureme" }
10+
tools_lib = { path = "../tools_lib" }
11+
structopt = "0.2"
12+
inferno = { version="0.9.1", default-features = false }

flamegraph/README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# flamegraph
2+
3+
flamegraph is a tool to produce [Flame Graph](https://github.com/brendangregg/FlameGraph) from `measureme` data.
4+
5+
## Example
6+
7+
```bash
8+
$ git clone https://github.com/rust-lang/regex.git
9+
10+
$ cd regex
11+
12+
$ cargo rustc -- -Z self-profile
13+
14+
$ flamegraph pid-{pid}
15+
16+
$ open rustc.svg
17+
```

flamegraph/src/main.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
use std::error::Error;
2+
use std::fs::File;
3+
use std::io::BufWriter;
4+
use std::path::PathBuf;
5+
use std::time::Duration;
6+
7+
use measureme::ProfilingData;
8+
9+
use structopt::StructOpt;
10+
11+
use tools_lib::stack_collapse::collapse_stacks;
12+
13+
use inferno::flamegraph::{from_lines, Options as FlamegraphOptions};
14+
15+
#[derive(StructOpt, Debug)]
16+
struct Opt {
17+
file_prefix: PathBuf,
18+
19+
/// The sampling interval in milliseconds
20+
#[structopt(short = "i", long = "interval", default_value = "1")]
21+
interval: u64,
22+
}
23+
24+
fn main() -> Result<(), Box<dyn Error>> {
25+
let opt = Opt::from_args();
26+
27+
let profiling_data = ProfilingData::new(&opt.file_prefix)?;
28+
29+
let first_event_time = {
30+
let current_time = profiling_data.iter().next().unwrap().timestamp;
31+
current_time + Duration::from_millis(opt.interval)
32+
};
33+
34+
let recorded_stacks = collapse_stacks(profiling_data.iter(), first_event_time, opt.interval)
35+
.iter()
36+
.map(|(unique_stack, count)| format!("{} {}", unique_stack, count))
37+
.collect::<Vec<_>>();
38+
39+
let file = BufWriter::new(File::create("rustc.svg")?);
40+
let mut flamegraph_options = FlamegraphOptions::default();
41+
42+
from_lines(
43+
&mut flamegraph_options,
44+
recorded_stacks.iter().map(|s| s.as_ref()),
45+
file,
46+
)
47+
.expect(
48+
"unable to generate a flamegraph \
49+
from the collapsed stack data",
50+
);
51+
52+
Ok(())
53+
}

stack_collapse/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ license = "MIT OR Apache-2.0"
77

88
[dependencies]
99
measureme = { path = "../measureme" }
10+
tools_lib = { path = "../tools_lib" }
1011
structopt = "0.2"

stack_collapse/src/main.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,7 @@ use measureme::ProfilingData;
88

99
use structopt::StructOpt;
1010

11-
mod stack_collapse;
12-
13-
use stack_collapse::collapse_stacks;
11+
use tools_lib::stack_collapse::collapse_stacks;
1412

1513
#[derive(StructOpt, Debug)]
1614
struct Opt {

tools_lib/Cargo.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[package]
2+
name = "tools_lib"
3+
version = "0.1.0"
4+
authors = ["Wesley Wiser <[email protected]>", "Michael Woerister <michaelwoerister@posteo>"]
5+
edition = "2018"
6+
license = "MIT OR Apache-2.0"
7+
8+
[dependencies]
9+
measureme = { path = "../measureme" }

tools_lib/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub mod stack_collapse;

0 commit comments

Comments
 (0)