use crate::backends::base::TracingBackend;
use crate::profile_result::ProfileResult;
use crate::profiler::Profiler;
use std::time::{Instant, SystemTime, UNIX_EPOCH};
pub struct ProfilerTimer {
name: String,
start_point: Instant,
start_timestamp: u64,
frame_index: usize,
thread_name: String,
is_stopped: bool,
}
impl ProfilerTimer {
pub fn new(name: &str) -> Self {
let frame_index = Profiler::get().lock().frame_count();
let thread_name = std::thread::current()
.name()
.unwrap_or("unnamed")
.to_string();
Self {
name: name.to_string(),
start_point: Instant::now(),
start_timestamp: timestamp_micros(),
frame_index,
thread_name,
is_stopped: false,
}
}
pub fn stop(&mut self) {
if self.is_stopped {
return;
}
self.is_stopped = true;
let dur = self.start_point.elapsed().as_micros() as u64;
let mut result = ProfileResult::complete(
self.name.clone(),
self.start_timestamp,
dur,
thread_id_u64(),
process_id_u64(),
);
result.args = Some(serde_json::json!({
"frame": self.frame_index,
"thread_name": self.thread_name,
}));
Profiler::get().lock().record_event(&result);
}
}
impl Drop for ProfilerTimer {
fn drop(&mut self) {
if !self.is_stopped {
self.stop();
}
}
}
fn timestamp_micros() -> u64 {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_micros() as u64
}
fn thread_id_u64() -> u64 {
let tid = format!("{:?}", std::thread::current().id());
tid.trim_start_matches("ThreadId(")
.trim_end_matches(')')
.parse()
.unwrap_or(0)
}
fn process_id_u64() -> u64 {
std::process::id() as u64
}