1extern crate time;
2#[macro_use] extern crate lazy_static;
3
4mod profiler_frame;
5mod profiler_state;
6
7use std::sync::Mutex;
8use time::precise_time_s;
9use std::ops::Drop;
10
11pub use profiler_frame::*;
12pub use profiler_state::*;
13
14lazy_static! {
15 pub static ref PROFILER_STATE: Mutex<ProfilerState> = Mutex::new(ProfilerState::new());
16}
17
18#[derive(Debug)]
19pub struct ProfilerReport {
20 pub name : String,
21 pub time : f64,
22 pub percent : f64,
23 pub sub_reports : Vec<ProfilerReport>
24}
25
26pub fn profiler_report() -> ProfilerReport {
27 state_report(&mut *PROFILER_STATE.lock().unwrap())
28}
29pub fn profiler_next_frame() {
30 PROFILER_STATE.lock().unwrap().next_frame();
31}
32
33pub struct ProfilerRegion {
34 pub enter_time : f64,
35 pub name : String
36}
37impl ProfilerRegion {
38 pub fn new(name : &str) -> ProfilerRegion {
39 PROFILER_STATE.lock().unwrap().begin_track_time(name.to_string());
40 ProfilerRegion {
41 enter_time : precise_time_s(),
42 name : name.to_string()
43 }
44 }
45}
46impl Drop for ProfilerRegion {
47 fn drop(&mut self) {
48 PROFILER_STATE.lock().unwrap().end_track_time(precise_time_s() - self.enter_time);
49 }
50}
51
52
53#[macro_export]
54macro_rules! profile_region {
55 ($name:expr) => {
56 let _profile = $crate::ProfilerRegion::new($name);
57 }
58}
59
60#[macro_export]
61macro_rules! print_region_time {
62 ($x:expr, $pattern:expr) => {{
63 use time::precise_time_s;
64
65 let start = precise_time_s();
66 let res = $x;
67 let end = precise_time_s();
68 println!($pattern, end - start);
69 res
70 }};
71}
72
73pub fn state_report(state : &mut ProfilerState) -> ProfilerReport {
74 let frame = state.previous_frame();
75 report(&frame.counters, frame.end_time - frame.begin_time)
76}
77
78fn report(counter : &ProfilerCounter, time : f64) -> ProfilerReport {
79 ProfilerReport {
80 name : counter.name.clone(),
81 time : counter.time,
82 percent : counter.time / time * 100.0,
83 sub_reports : counter.counters.iter().map(|x| report(x, counter.time)).collect()
84 }
85}
86
87#[test]
88fn test_print_region_time() {
89 let _ : i32 = print_region_time!({
90 (1 ..).take(1000).fold(0, |x, y| x + y)
91 }, "Something time tooked: {}");
92}
93
94#[test]
95fn test_track_regions() {
96 {
97 profile_region!("Main region");
98
99 (1 ..).take(500000).fold(0, |x, y| ((x * y) as f32).sqrt().sin() as i32 + 1);
100
101 {
102 profile_region!("subregion 1");
103 (1 ..).take(500000).fold(0, |x, y| ((x * y) as f32).sqrt().sin() as i32 + 1);
104 }
105
106 {
107 profile_region!("subregion 2");
108 (1 ..).take(500000).fold(0, |x, y| ((x * y) as f32).sqrt().sin() as i32 + 1);
109
110 {
111 profile_region!("subsubregion 1");
112 (1 ..).take(500000).fold(0, |x, y| ((x * y) as f32).sqrt().sin() as i32 + 1);
113 }
114
115 {
116 profile_region!("subsubregion 2");
117 (1 ..).take(500000).fold(0, |x, y| ((x * y) as f32).sqrt().sin() as i32 + 1);
118 }
119
120 }
121
122 {
123 profile_region!("subregion 3");
124 (1 ..).take(500000).fold(0, |x, y| ((x * y) as f32).sqrt().sin() as i32 + 1);
125 }
126 }
127
128 profiler_next_frame();
129
130 println!("{:?}", profiler_report());
131}