1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
mod stop_watch;
mod memory_usage;
#[cfg(feature = "cpu_profiler")]
mod google_cpu_profiler;
mod hprof;
mod tree;
use std::cell::RefCell;
pub use crate::{
hprof::{heartbeat, heartbeat_span, init, init_from, span},
memory_usage::{Bytes, MemoryUsage},
stop_watch::{StopWatch, StopWatchSpan},
};
pub use countme;
pub use countme::Count;
thread_local!(static IN_SCOPE: RefCell<bool> = RefCell::new(false));
pub struct Scope {
prev: bool,
}
impl Scope {
#[must_use]
pub fn enter() -> Scope {
let prev = IN_SCOPE.with(|slot| std::mem::replace(&mut *slot.borrow_mut(), true));
Scope { prev }
}
pub fn is_active() -> bool {
IN_SCOPE.with(|slot| *slot.borrow())
}
}
impl Drop for Scope {
fn drop(&mut self) {
IN_SCOPE.with(|slot| *slot.borrow_mut() = self.prev);
}
}
#[derive(Debug)]
pub struct CpuSpan {
_private: (),
}
#[must_use]
pub fn cpu_span() -> CpuSpan {
#[cfg(feature = "cpu_profiler")]
{
google_cpu_profiler::start("./out.profile".as_ref())
}
#[cfg(not(feature = "cpu_profiler"))]
{
eprintln!(
r#"cpu profiling is disabled, uncomment `default = [ "cpu_profiler" ]` in Cargo.toml to enable."#
)
}
CpuSpan { _private: () }
}
impl Drop for CpuSpan {
fn drop(&mut self) {
#[cfg(feature = "cpu_profiler")]
{
google_cpu_profiler::stop();
let profile_data = std::env::current_dir().unwrap().join("out.profile");
eprintln!("Profile data saved to:\n\n {}\n", profile_data.display());
let mut cmd = std::process::Command::new("pprof");
cmd.arg("-svg").arg(std::env::current_exe().unwrap()).arg(&profile_data);
let out = cmd.output();
match out {
Ok(out) if out.status.success() => {
let svg = profile_data.with_extension("svg");
std::fs::write(&svg, &out.stdout).unwrap();
eprintln!("Profile rendered to:\n\n {}\n", svg.display());
}
_ => {
eprintln!("Failed to run:\n\n {:?}\n", cmd);
}
}
}
}
}
pub fn memory_usage() -> MemoryUsage {
MemoryUsage::now()
}