1use std::collections::HashMap;
2
3use crate::{
4 alloc::ThreadAllocInfo,
5 counter::KnownCounterKind,
6 time::{FineDuration, Timer, Timestamp},
7};
8
9/// Timing measurement.
10pub(crate) struct TimeSample {
11 /// The time this sample took to run.
12 ///
13 /// This is gotten from [`RawSample`] with:
14 /// `end.duration_since(start, timer).clamp_to(timer.precision())`.
15 pub duration: FineDuration,
16}
17
18/// Unprocessed measurement.
19///
20/// This cannot be serialized because [`Timestamp`] is an implementation detail
21/// for both the `Instant` and TSC timers.
22pub(crate) struct RawSample {
23 pub start: Timestamp,
24 pub end: Timestamp,
25 pub timer: Timer,
26 pub alloc_info: ThreadAllocInfo,
27 pub counter_totals: [u128; KnownCounterKind::COUNT],
28}
29
30impl RawSample {
31 /// Simply computes `end - start` without clamping to precision.
32 #[inline]
33 pub fn duration(&self) -> FineDuration {
34 self.end.duration_since(self.start, self.timer)
35 }
36}
37
38/// Sample collection.
39#[derive(Default)]
40pub(crate) struct SampleCollection {
41 /// The number of iterations within each sample.
42 pub sample_size: u32,
43
44 /// Collected timings.
45 pub time_samples: Vec<TimeSample>,
46
47 /// Allocation information associated with `time_samples` by index.
48 pub alloc_info_by_sample: HashMap<u32, ThreadAllocInfo>,
49}
50
51impl SampleCollection {
52 /// Discards all recorded data.
53 #[inline]
54 pub fn clear(&mut self) {
55 self.time_samples.clear();
56 self.alloc_info_by_sample.clear();
57 }
58
59 /// Computes the total number of iterations across all samples.
60 ///
61 /// We use `u64` in case sample count and sizes are huge.
62 #[inline]
63 pub fn iter_count(&self) -> u64 {
64 self.sample_size as u64 * self.time_samples.len() as u64
65 }
66
67 /// Computes the total time across all samples.
68 #[inline]
69 pub fn total_duration(&self) -> FineDuration {
70 FineDuration { picos: self.time_samples.iter().map(|s| s.duration.picos).sum() }
71 }
72
73 /// Returns all samples sorted by duration.
74 #[inline]
75 pub fn sorted_samples(&self) -> Vec<&TimeSample> {
76 let mut result: Vec<&TimeSample> = self.time_samples.iter().collect();
77 result.sort_unstable_by_key(|s| s.duration);
78 result
79 }
80}
81