summaryrefslogtreecommitdiff
path: root/profiler
diff options
context:
space:
mode:
Diffstat (limited to 'profiler')
-rw-r--r--profiler/Cargo.toml10
-rw-r--r--profiler/src/lib.rs103
2 files changed, 113 insertions, 0 deletions
diff --git a/profiler/Cargo.toml b/profiler/Cargo.toml
new file mode 100644
index 0000000..d9c7f2b
--- /dev/null
+++ b/profiler/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "alligator_profiler"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+alligator_console = { path = "../console" }
+
+scopeguard = "1"
+chrono = "0.4" \ No newline at end of file
diff --git a/profiler/src/lib.rs b/profiler/src/lib.rs
new file mode 100644
index 0000000..d23ad24
--- /dev/null
+++ b/profiler/src/lib.rs
@@ -0,0 +1,103 @@
+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!());
+ };
+}