git_perf/
measurement_retrieval.rs1use crate::{
2 data::{CommitSummary, MeasurementData, MeasurementSummary, ReductionFunc},
3 git_interop::{self},
4 stats::NumericReductionFunc,
5};
6
7use anyhow::Result;
8
9pub trait ReductionFuncIterator<'a>: Iterator<Item = &'a MeasurementData> {
11 fn reduce_by(self, fun: ReductionFunc) -> Option<MeasurementSummary>;
12}
13
14pub fn summarize_measurements<'a, F>(
15 commits: impl Iterator<Item = Result<Commit>> + 'a,
16 summarize_by: &'a ReductionFunc,
17 filter_by: &'a F,
18) -> impl Iterator<Item = Result<CommitSummary>> + 'a
19where
20 F: Fn(&MeasurementData) -> bool,
21{
22 let measurements = commits.map(move |c| {
23 c.map(|c| {
24 let measurement = c
25 .measurements
26 .iter()
27 .filter(|m| filter_by(m))
28 .reduce_by(*summarize_by);
29
30 CommitSummary {
31 commit: c.commit,
32 measurement,
33 }
34 })
35 });
36
37 let mut first_epoch = None;
38
39 measurements.take_while(move |m| match &m {
41 Ok(CommitSummary {
42 measurement: Some(m),
43 ..
44 }) => {
45 let prev_epoch = first_epoch;
46 first_epoch = Some(m.epoch);
47 prev_epoch.unwrap_or(m.epoch) == m.epoch
48 }
49 _ => true,
50 })
51}
52
53impl<'a, T> ReductionFuncIterator<'a> for T
54where
55 T: Iterator<Item = &'a MeasurementData>,
56{
57 fn reduce_by(self, fun: ReductionFunc) -> Option<MeasurementSummary> {
58 let mut peekable = self.peekable();
59 let expected_epoch = peekable.peek().map(|m| m.epoch);
60 let mut vals = peekable.map(|m| {
61 debug_assert_eq!(Some(m.epoch), expected_epoch);
62 m.val
63 });
64
65 let aggregate_val = vals.aggregate_by(fun);
66
67 Some(MeasurementSummary {
68 epoch: expected_epoch?,
69 val: aggregate_val?,
70 })
71 }
72}
73
74#[derive(Debug, PartialEq)]
75pub struct Commit {
76 pub commit: String,
77 pub measurements: Vec<MeasurementData>,
78}
79
80pub fn walk_commits(num_commits: usize) -> Result<impl Iterator<Item = Result<Commit>>> {
83 let vec = git_interop::walk_commits(num_commits)?;
84 Ok(vec
85 .into_iter()
86 .take(num_commits)
87 .map(|(commit_id, lines)| -> Result<Commit> {
88 let measurements = crate::serialization::deserialize(&lines.join("\n"));
89 Ok(Commit {
90 commit: commit_id,
91 measurements,
92 })
93 }))
94 }