1use context_manager::{CallerContext, SyncWrapContext};
3use log::debug;
4use std::marker::PhantomData;
5use std::sync::{LazyLock, Mutex};
6use std::time::Instant;
7
8static INVESTMENT_TIME: LazyLock<Mutex<f64>> = LazyLock::new(|| Mutex::new(0.0));
10
11static DISPATCH_TIME: LazyLock<Mutex<f64>> = LazyLock::new(|| Mutex::new(0.0));
13
14pub trait TimeContext {
16 fn label(caller_context: &CallerContext) -> String;
18
19 fn accumulate(milliseconds: &f64);
21
22 fn total_time() -> f64 {
24 0.0
25 }
26}
27
28pub struct GenericTimer<C: TimeContext = GenericContext> {
30 start: Instant,
31 _context: PhantomData<C>, }
33
34impl<T, C: TimeContext> SyncWrapContext<T> for GenericTimer<C> {
35 fn new() -> Self {
36 Self {
37 start: Instant::now(),
38 _context: PhantomData,
39 }
40 }
41
42 fn after(self, caller_context: &CallerContext, _result: &T) {
43 let label = C::label(caller_context);
44 let ms = self.start.elapsed().as_secs_f64() * 1000.0;
45 C::accumulate(&ms);
46 debug!("{label} completed in {ms:.1}ms");
47 }
48}
49
50pub struct GenericContext;
53impl TimeContext for GenericContext {
54 fn label(caller_context: &CallerContext) -> String {
55 let fn_name = caller_context.fn_name();
56 format!("[Timer] '{fn_name}'")
57 }
58 fn accumulate(_milliseconds: &f64) {}
59}
60
61pub struct InvestmentContext;
64impl TimeContext for InvestmentContext {
65 fn label(_: &CallerContext) -> String {
66 "Investment step".to_string()
67 }
68 fn accumulate(milliseconds: &f64) {
69 let mut investment_time = INVESTMENT_TIME.lock().unwrap();
70 *investment_time += *milliseconds;
71 }
72 fn total_time() -> f64 {
73 let investment_time = INVESTMENT_TIME.lock().unwrap();
74 *investment_time
75 }
76}
77
78pub struct DispatchContext;
81impl TimeContext for DispatchContext {
82 fn label(_: &CallerContext) -> String {
83 "Dispatch step".to_string()
84 }
85 fn accumulate(milliseconds: &f64) {
86 let mut dispatch_time = DISPATCH_TIME.lock().unwrap();
87 *dispatch_time += *milliseconds;
88 }
89 fn total_time() -> f64 {
90 let dispatch_time = DISPATCH_TIME.lock().unwrap();
91 *dispatch_time
92 }
93}
94
95pub type InvestmentTimer = GenericTimer<InvestmentContext>;
97
98pub type DispatchTimer = GenericTimer<DispatchContext>;