git_perf/
measurement_retrieval.rs1use crate::{
2 data::{Commit, CommitSummary, MeasurementData, MeasurementSummary},
3 git::git_interop::{self},
4 stats::{NumericReductionFunc, ReductionFunc},
5};
6
7use anyhow::Result;
8
9pub trait MeasurementReducer<'a>: Iterator<Item = &'a MeasurementData> {
10 fn reduce_by(self, fun: ReductionFunc) -> Option<MeasurementSummary>;
11}
12
13pub fn summarize_measurements<'a, F>(
14 commits: impl Iterator<Item = Result<Commit>> + 'a,
15 summarize_by: &'a ReductionFunc,
16 filter_by: &'a F,
17) -> impl Iterator<Item = Result<CommitSummary>> + 'a
18where
19 F: Fn(&MeasurementData) -> bool,
20{
21 commits.map(move |c| {
22 c.map(|c| {
23 let measurement = c
24 .measurements
25 .iter()
26 .filter(|m| filter_by(m))
27 .reduce_by(*summarize_by);
28
29 CommitSummary {
30 commit: c.commit,
31 measurement,
32 }
33 })
34 })
35}
36
37pub fn take_while_same_epoch<I>(iter: I) -> impl Iterator<Item = Result<CommitSummary>>
39where
40 I: Iterator<Item = Result<CommitSummary>>,
41{
42 let mut first_epoch: Option<u32> = None;
43 iter.take_while(move |m| match m {
44 Ok(CommitSummary {
45 measurement: Some(m),
46 ..
47 }) => {
48 let prev_epoch = first_epoch;
49 first_epoch = Some(m.epoch);
50 prev_epoch.unwrap_or(m.epoch) == m.epoch
51 }
52 _ => true,
53 })
54}
55
56impl<'a, T> MeasurementReducer<'a> for T
57where
58 T: Iterator<Item = &'a MeasurementData>,
59{
60 fn reduce_by(self, fun: ReductionFunc) -> Option<MeasurementSummary> {
61 let mut peekable = self.peekable();
62 let expected_epoch = peekable.peek().map(|m| m.epoch);
63 let mut vals = peekable.map(|m| {
64 debug_assert_eq!(Some(m.epoch), expected_epoch);
65 m.val
66 });
67
68 let aggregate_val = vals.aggregate_by(fun);
69
70 Some(MeasurementSummary {
71 epoch: expected_epoch?,
72 val: aggregate_val?,
73 })
74 }
75}
76
77pub fn walk_commits_from(
116 start_commit: &str,
117 num_commits: usize,
118 since: Option<&str>,
119 until: Option<&str>,
120) -> Result<impl Iterator<Item = Result<Commit>>> {
121 let vec = git_interop::walk_commits_from(start_commit, num_commits, since, until)?;
122 Ok(vec
123 .into_iter()
124 .take(num_commits)
125 .map(|commit_data| -> Result<Commit> {
126 let measurements =
127 crate::serialization::deserialize(&commit_data.note_lines.join("\n"));
128 Ok(Commit {
129 commit: commit_data.sha,
130 title: commit_data.title,
131 author: commit_data.author,
132 measurements,
133 })
134 }))
135 }