40 lines
1.1 KiB
Rust
40 lines
1.1 KiB
Rust
//! https://github.com/gperftools/gperftools
|
|
|
|
use std::{
|
|
ffi::CString,
|
|
os::raw::c_char,
|
|
path::Path,
|
|
sync::atomic::{AtomicUsize, Ordering},
|
|
};
|
|
|
|
#[link(name = "profiler")]
|
|
#[allow(non_snake_case)]
|
|
extern "C" {
|
|
fn ProfilerStart(fname: *const c_char) -> i32;
|
|
fn ProfilerStop();
|
|
}
|
|
|
|
static PROFILER_STATE: AtomicUsize = AtomicUsize::new(OFF);
|
|
const OFF: usize = 0;
|
|
const ON: usize = 1;
|
|
const PENDING: usize = 2;
|
|
|
|
pub fn start(path: &Path) {
|
|
if PROFILER_STATE.compare_and_swap(OFF, PENDING, Ordering::SeqCst) != OFF {
|
|
panic!("profiler already started");
|
|
}
|
|
let path = CString::new(path.display().to_string()).unwrap();
|
|
if unsafe { ProfilerStart(path.as_ptr()) } == 0 {
|
|
panic!("profiler failed to start")
|
|
}
|
|
assert!(PROFILER_STATE.compare_and_swap(PENDING, ON, Ordering::SeqCst) == PENDING);
|
|
}
|
|
|
|
pub fn stop() {
|
|
if PROFILER_STATE.compare_and_swap(ON, PENDING, Ordering::SeqCst) != ON {
|
|
panic!("profiler is not started")
|
|
}
|
|
unsafe { ProfilerStop() };
|
|
assert!(PROFILER_STATE.compare_and_swap(PENDING, OFF, Ordering::SeqCst) == PENDING);
|
|
}
|