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 129 130 131
extern crate time; #[macro_use] extern crate lazy_static; mod profiler_frame; mod profiler_state; use std::sync::Mutex; use time::precise_time_s; use std::ops::Drop; pub use profiler_frame::*; pub use profiler_state::*; lazy_static! { pub static ref PROFILER_STATE: Mutex<ProfilerState> = Mutex::new(ProfilerState::new()); } #[derive(Debug)] pub struct ProfilerReport { pub name : String, pub time : f64, pub percent : f64, pub sub_reports : Vec<ProfilerReport> } pub fn profiler_report() -> ProfilerReport { state_report(&mut *PROFILER_STATE.lock().unwrap()) } pub fn profiler_next_frame() { PROFILER_STATE.lock().unwrap().next_frame(); } pub struct ProfilerRegion { pub enter_time : f64, pub name : String } impl ProfilerRegion { pub fn new(name : &str) -> ProfilerRegion { PROFILER_STATE.lock().unwrap().begin_track_time(name.to_string()); ProfilerRegion { enter_time : precise_time_s(), name : name.to_string() } } } impl Drop for ProfilerRegion { fn drop(&mut self) { PROFILER_STATE.lock().unwrap().end_track_time(precise_time_s() - self.enter_time); } } #[macro_export] macro_rules! profile_region { ($name:expr) => { let _profile = $crate::ProfilerRegion::new($name); } } #[macro_export] macro_rules! print_region_time { ($x:expr, $pattern:expr) => {{ use time::precise_time_s; let start = precise_time_s(); let res = $x; let end = precise_time_s(); println!($pattern, end - start); res }}; } pub fn state_report(state : &mut ProfilerState) -> ProfilerReport { let frame = state.previous_frame(); report(&frame.counters, frame.end_time - frame.begin_time) } fn report(counter : &ProfilerCounter, time : f64) -> ProfilerReport { ProfilerReport { name : counter.name.clone(), time : counter.time, percent : counter.time / time * 100.0, sub_reports : counter.counters.iter().map(|x| report(x, counter.time)).collect() } } #[test] fn test_print_region_time() { let _ : i32 = print_region_time!({ (1 ..).take(1000).fold(0, |x, y| x + y) }, "Something time tooked: {}"); } #[test] fn test_track_regions() { { profile_region!("Main region"); (1 ..).take(500000).fold(0, |x, y| ((x * y) as f32).sqrt().sin() as i32 + 1); { profile_region!("subregion 1"); (1 ..).take(500000).fold(0, |x, y| ((x * y) as f32).sqrt().sin() as i32 + 1); } { profile_region!("subregion 2"); (1 ..).take(500000).fold(0, |x, y| ((x * y) as f32).sqrt().sin() as i32 + 1); { profile_region!("subsubregion 1"); (1 ..).take(500000).fold(0, |x, y| ((x * y) as f32).sqrt().sin() as i32 + 1); } { profile_region!("subsubregion 2"); (1 ..).take(500000).fold(0, |x, y| ((x * y) as f32).sqrt().sin() as i32 + 1); } } { profile_region!("subregion 3"); (1 ..).take(500000).fold(0, |x, y| ((x * y) as f32).sqrt().sin() as i32 + 1); } } profiler_next_frame(); println!("{:?}", profiler_report()); }