blob: d23ad24bc5d2f7d90ec6fc936201564da7aa3715 (
plain)
use std::sync::OnceLock;
use alligator_console::{ConsoleLogger, ConsoleMessage};
use chrono::{DateTime, Utc};
use scopeguard::ScopeGuard;
static GLOBAL_PROFILER: OnceLock<Profiler> = OnceLock::new();
struct Profiler {
logger: ConsoleLogger,
start_time: DateTime<Utc>,
}
impl Profiler {
fn new(logger: ConsoleLogger) -> Self {
Self {
logger,
start_time: Utc::now(),
}
}
fn current_timestamp(&self) -> i64 {
Utc::now()
.signed_duration_since(DateTime::UNIX_EPOCH)
.num_microseconds()
.unwrap_or(i64::MAX)
}
fn finish_frame(&self) {
self.logger.send(ConsoleMessage::FrameTime {
timestamp: self.current_timestamp(),
})
}
fn start_scope(&self, scope_name: String) {
self.logger.send(ConsoleMessage::ScopeStart {
scope_name,
timestamp: self.current_timestamp(),
})
}
fn end_scope(&self) {
self.logger.send(ConsoleMessage::ScopeEnd {
timestamp: self.current_timestamp(),
})
}
}
pub fn set_profiler(logger: ConsoleLogger) {
GLOBAL_PROFILER.get_or_init(|| Profiler::new(logger));
}
pub fn finish_frame() {
GLOBAL_PROFILER.get().unwrap().finish_frame();
}
pub fn start_scope(scope_name: impl AsRef<str>) {
GLOBAL_PROFILER
.get()
.unwrap()
.start_scope(scope_name.as_ref().to_string());
}
pub fn end_scope() {
GLOBAL_PROFILER.get().unwrap().end_scope();
}
pub fn profile_scope(scope_name: impl AsRef<str>) -> ScopeGuard<(), impl FnOnce(())> {
start_scope(scope_name);
scopeguard::guard((), |_| end_scope())
}
#[macro_export]
macro_rules! scope {
($scope_name: expr) => {
let _profiling_scope = $crate::profile_scope($scope_name);
};
() => {
let _profiling_scope = $crate::profile_scope("unnamed scope");
};
}
#[macro_export]
macro_rules! function_name {
() => {{
fn f() {}
fn type_name_of<T>(_: T) -> &'static str {
std::any::type_name::<T>()
}
type_name_of(f)
.split("::")
.filter(|&part| part != "f")
.collect::<Vec<&str>>()
.join("::")
}};
}
#[macro_export]
macro_rules! profile_function {
() => {
$crate::scope!($crate::function_name!());
};
}
|