#[cfg(feature = "debug")]
type Inner = Option<(pprof::ProfilerGuard<'static>, String)>;
#[cfg(not(feature = "debug"))]
type Inner = ();
pub struct ProfileGuard {
#[allow(dead_code)] inner: Inner,
}
impl ProfileGuard {
pub fn start(path: Option<&str>) -> Self {
#[cfg(feature = "debug")]
{
let inner = path.map(|p| {
let g = pprof::ProfilerGuardBuilder::default()
.frequency(1000)
.blocklist(&["libc", "libgcc", "pthread", "vdso"])
.build()
.expect("profiler start");
(g, p.to_string())
});
Self { inner }
}
#[cfg(not(feature = "debug"))]
{
if path.is_some() {
eprintln!("warning: --pprof requires building with `--features debug`");
}
Self { inner: () }
}
}
pub fn finish(self) {
#[cfg(feature = "debug")]
if let Some((g, path)) = self.inner {
match g.report().build() {
Ok(report) => match std::fs::File::create(&path) {
Ok(file) => {
if let Err(e) = report.flamegraph(file) {
eprintln!("flamegraph write failed: {e}");
} else {
eprintln!("wrote flamegraph: {path}");
}
}
Err(e) => eprintln!("flamegraph create failed: {e}"),
},
Err(e) => eprintln!("profiler report failed: {e}"),
}
}
}
}