1use serde::Serialize;
2use std::time::Instant;
3
4#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
5pub struct PhaseTiming {
6 pub phase: String,
7 pub elapsed_ms: u64,
8}
9
10impl PhaseTiming {
11 pub fn elapsed(phase: impl Into<String>, start: Instant) -> Self {
12 Self {
13 phase: phase.into(),
14 elapsed_ms: start.elapsed().as_millis() as u64,
15 }
16 }
17}
18
19pub fn time_result<T>(
20 timings: &mut Vec<PhaseTiming>,
21 phase: &'static str,
22 f: impl FnOnce() -> anyhow::Result<T>,
23) -> anyhow::Result<T> {
24 let start = Instant::now();
25 let result = f();
26 timings.push(PhaseTiming::elapsed(phase, start));
27 result
28}
29
30pub fn time_value<T>(
31 timings: &mut Vec<PhaseTiming>,
32 phase: &'static str,
33 f: impl FnOnce() -> T,
34) -> T {
35 let start = Instant::now();
36 let value = f();
37 timings.push(PhaseTiming::elapsed(phase, start));
38 value
39}
40
41pub fn push_elapsed(timings: &mut Vec<PhaseTiming>, phase: &'static str, start: Instant) {
42 timings.push(PhaseTiming::elapsed(phase, start));
43}
44
45pub fn format_phase_timings(timings: &[PhaseTiming]) -> String {
46 timings
47 .iter()
48 .map(|timing| format!("{}={}ms", timing.phase, timing.elapsed_ms))
49 .collect::<Vec<_>>()
50 .join(" ")
51}