tikv / pprof-rs

A Rust CPU profiler implemented with the help of backtrace-rs
Apache License 2.0
1.29k stars 99 forks source link

[Bug]Report is empty? #176

Open Fomalhauthmj opened 1 year ago

Fomalhauthmj commented 1 year ago

I found following test code can't collect any data during execution, and the flamegraph is blank.

fn main() {
    let guard = pprof::ProfilerGuardBuilder::default()
        .frequency(1000)
        .blocklist(&["libc", "libgcc", "pthread", "vdso"])
        .build()
        .unwrap();
    let mut sum = 0;
    for i in 0..1_000 {
        sum += i;
    }
    println!("{:?}", sum);
    if let Ok(report) = guard.report().build() {
        println!("report: {:?}", &report);
        let file = std::fs::File::create("flamegraph.svg").unwrap();
        report.flamegraph(file).unwrap();
    }
}

cargo run's output:

    Finished dev [unoptimized + debuginfo] target(s) in 0.04s
     Running `target/debug/rust_test`
499500
report: 

My test environment:

Ubuntu 22.04 LTS
cargo 1.65.0 (4bc8f24d3 2022-10-20)
pprof = { version = "0.11.0", features = ["flamegraph"] }
YangKeao commented 1 year ago

I guess it's simply because this program runs too fast, and no sample has been caught...

fn main() {
    let guard = pprof::ProfilerGuardBuilder::default()
        .frequency(1000)
        .blocklist(&["libc", "libgcc", "pthread", "vdso"])
        .build()
        .unwrap();
    let mut sum = 0;
    for i in 1..1_000_000_000 {
        for j in 1..i {
            for k in 1..10 {
                sum += i*j*k;
            }
        }
    }
    println!("{:?}", sum);
    if let Ok(report) = guard.report().build() {
        println!("report: {:?}", &report);
        let file = std::fs::File::create("flamegraph.svg").unwrap();
        report.flamegraph(file).unwrap();
    }
}

Will give you one backtrace through cargo run --release (all sample hits main, so there is only a single backtrace). This example has to run with --release, or it will panic because plus overflow.

Fomalhauthmj commented 1 year ago

Thx, I have solved this problem. By the way,what's the background of frequency in the builder? Because my real workload take time nearly 3ms(walltime), so l set frequency to 1000.However it's output is the same with above example,which made me confused. I check the source code of pprof:

impl Timer {
    pub fn new(frequency: c_int) -> Timer {
        let interval = 1e6 as i64 / i64::from(frequency);
        let it_interval = Timeval {
            tv_sec: interval / 1e6 as i64,
            tv_usec: interval % 1e6 as i64,
        };
        ......
    }

It looks like that frequency should less than 1e6.

viglia commented 1 year ago

Not sure if this is the case but it could be related to issue #177