Skip to main content

symbolicate/
symbolicate.rs

1//! Symbolicated per-call-site report demo.
2//!
3//! Run with:
4//!   cargo run --release --features symbolicate --example symbolicate
5//!
6//! Requires frame pointers in the build (`.cargo/config.toml`
7//! already sets this for in-crate runs) and debug info present in
8//! the binary (the default `cargo run --release` build keeps
9//! enough info for `addr2line` / `pdb` to resolve our own
10//! functions).
11
12#[cfg(feature = "symbolicate")]
13#[global_allocator]
14static GLOBAL: mod_alloc::ModAlloc = mod_alloc::ModAlloc::new();
15
16#[cfg(feature = "symbolicate")]
17#[inline(never)]
18fn alloc_small() {
19    let v: Vec<u8> = Vec::with_capacity(64);
20    std::hint::black_box(&v);
21}
22
23#[cfg(feature = "symbolicate")]
24#[inline(never)]
25fn alloc_medium() {
26    let v: Vec<u8> = Vec::with_capacity(1024);
27    std::hint::black_box(&v);
28}
29
30#[cfg(feature = "symbolicate")]
31#[inline(never)]
32fn alloc_large() {
33    let v: Vec<u8> = Vec::with_capacity(64 * 1024);
34    std::hint::black_box(&v);
35}
36
37#[cfg(feature = "symbolicate")]
38fn main() {
39    for _ in 0..500 {
40        alloc_small();
41    }
42    for _ in 0..100 {
43        alloc_medium();
44    }
45    for _ in 0..10 {
46        alloc_large();
47    }
48
49    let mut report = GLOBAL.symbolicated_report();
50    report.sort_by_key(|s| std::cmp::Reverse(s.total_bytes));
51
52    let snap = GLOBAL.snapshot();
53    println!("Process-wide:");
54    println!(
55        "  {} allocations, {} total bytes, peak {} bytes",
56        snap.alloc_count, snap.total_bytes, snap.peak_bytes
57    );
58    println!();
59
60    println!("Top call sites by total bytes:");
61    println!(
62        "{:>2}  {:>10}  {:>14}  top frame",
63        "#", "count", "total_bytes"
64    );
65    for (rank, site) in report.iter().take(10).enumerate() {
66        let top = &site.frames[0];
67        let name = top.function.as_deref().unwrap_or("<unresolved>");
68        let loc = match (top.file.as_ref(), top.line) {
69            (Some(f), Some(l)) => format!("  {}:{}", f.display(), l),
70            _ => String::new(),
71        };
72        println!(
73            "{rank:>2}  {count:>10}  {bytes:>14}  {name}{loc}",
74            rank = rank,
75            count = site.count,
76            bytes = site.total_bytes,
77            name = name,
78            loc = loc,
79        );
80        // Show inlined expansions if any.
81        for inlined in site.frames.iter().skip(1).take_while(|f| f.inlined) {
82            let n = inlined.function.as_deref().unwrap_or("<unresolved>");
83            println!("        inlined: {n}");
84        }
85    }
86}
87
88#[cfg(not(feature = "symbolicate"))]
89fn main() {
90    eprintln!(
91        "this example requires the `symbolicate` feature; run with \
92         `cargo run --features symbolicate --example symbolicate`"
93    );
94}