Skip to content

Commit 3d91c4c

Browse files
Merge pull request #1052 from tgnottingham/graph-perf
Make single query for graph data
2 parents 3d52444 + 1f9570b commit 3d91c4c

File tree

1 file changed

+41
-46
lines changed

1 file changed

+41
-46
lines changed

site/src/request_handlers/graph.rs

Lines changed: 41 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -45,27 +45,31 @@ async fn graph_response(
4545
) -> ServerResult<Arc<graph::Response>> {
4646
let range = ctxt.data_range(body.start..=body.end);
4747
let commits: Arc<Vec<_>> = Arc::new(range.into_iter().map(|c| c.into()).collect());
48-
let metric_selector = Selector::One(body.stat);
4948
let mut benchmarks = HashMap::new();
5049

51-
let series_iterator = ctxt
50+
let interpolated_responses: Vec<_> = ctxt
5251
.statistic_series(
5352
Query::new()
5453
.set::<String>(Tag::Benchmark, Selector::All)
5554
.set::<String>(Tag::Profile, Selector::All)
5655
.set::<String>(Tag::Scenario, Selector::All)
57-
.set::<String>(Tag::Metric, metric_selector.clone()),
56+
.set::<String>(Tag::Metric, Selector::One(body.stat)),
5857
commits.clone(),
5958
)
6059
.await?
6160
.into_iter()
62-
.map(SeriesResponse::interpolate);
61+
.map(|sr| sr.interpolate().map(|series| series.collect::<Vec<_>>()))
62+
.collect();
6363

64-
for series_response in series_iterator {
65-
let benchmark = series_response.path.get::<Benchmark>()?.to_string();
66-
let profile = *series_response.path.get::<Profile>()?;
67-
let scenario = series_response.path.get::<Scenario>()?.to_string();
68-
let graph_series = graph_series(series_response.series, body.kind);
64+
let summary_benchmark = create_summary(ctxt, &interpolated_responses, body.kind)?;
65+
66+
benchmarks.insert("Summary".to_string(), summary_benchmark);
67+
68+
for response in interpolated_responses {
69+
let benchmark = response.path.get::<Benchmark>()?.to_string();
70+
let profile = *response.path.get::<Profile>()?;
71+
let scenario = response.path.get::<Scenario>()?.to_string();
72+
let graph_series = graph_series(response.series.into_iter(), body.kind);
6973

7074
benchmarks
7175
.entry(benchmark)
@@ -75,10 +79,6 @@ async fn graph_response(
7579
.insert(scenario, graph_series);
7680
}
7781

78-
let summary_benchmark = create_summary(ctxt, metric_selector, &commits, body.kind).await?;
79-
80-
benchmarks.insert("Summary".to_string(), summary_benchmark);
81-
8282
Ok(Arc::new(graph::Response {
8383
commits: Arc::try_unwrap(commits)
8484
.unwrap()
@@ -94,10 +94,9 @@ async fn graph_response(
9494

9595
/// Creates a summary "benchmark" that averages the results of all other
9696
/// test cases per profile type
97-
async fn create_summary(
97+
fn create_summary(
9898
ctxt: &SiteCtxt,
99-
metric_selector: Selector<String>,
100-
commits: &Arc<Vec<ArtifactId>>,
99+
interpolated_responses: &[SeriesResponse<Vec<((ArtifactId, Option<f64>), IsInterpolated)>>],
101100
graph_kind: GraphKind,
102101
) -> ServerResult<HashMap<Profile, HashMap<String, graph::Series>>> {
103102
let mut baselines = HashMap::new();
@@ -107,42 +106,38 @@ async fn create_summary(
107106
vec![Profile::Check, Profile::Debug, Profile::Opt]
108107
);
109108
for (scenario, profile) in summary_query_cases {
110-
let query = Query::new()
111-
.set::<String>(Tag::Benchmark, Selector::All)
112-
.set(Tag::Profile, Selector::One(profile))
113-
.set(Tag::Scenario, Selector::One(scenario))
114-
.set(Tag::Metric, metric_selector.clone());
115-
116-
let baseline_query = Query::new()
117-
.set::<String>(Tag::Benchmark, Selector::All)
118-
.set(Tag::Profile, Selector::One(profile))
119-
.set(Tag::Scenario, Selector::One(Scenario::Empty))
120-
.set(Tag::Metric, metric_selector.clone());
121-
122-
let baseline = match baselines.entry(baseline_query.clone()) {
109+
let baseline = match baselines.entry((profile, scenario)) {
123110
std::collections::hash_map::Entry::Occupied(o) => *o.get(),
124111
std::collections::hash_map::Entry::Vacant(v) => {
125-
let value = db::average(
126-
ctxt.statistic_series(baseline_query, commits.clone())
127-
.await?
128-
.into_iter()
129-
.map(|sr| sr.interpolate().series)
130-
.collect::<Vec<_>>(),
131-
)
132-
.next()
133-
.map_or(0.0, |((_c, d), _interpolated)| d.expect("interpolated"));
112+
let baseline_responses = interpolated_responses
113+
.iter()
114+
.filter(|sr| {
115+
let p = sr.path.get::<Profile>().unwrap();
116+
let s = sr.path.get::<Scenario>().unwrap();
117+
*p == profile && *s == Scenario::Empty
118+
})
119+
.map(|sr| sr.series.iter().cloned())
120+
.collect();
121+
122+
let value = db::average(baseline_responses)
123+
.next()
124+
.map_or(0.0, |((_c, d), _interpolated)| d.expect("interpolated"));
134125
*v.insert(value)
135126
}
136127
};
137128

138-
let avg_vs_baseline = db::average(
139-
ctxt.statistic_series(query.clone(), commits.clone())
140-
.await?
141-
.into_iter()
142-
.map(|sr| sr.interpolate().series)
143-
.collect(),
144-
)
145-
.map(|((c, d), i)| ((c, Some(d.expect("interpolated") / baseline)), i));
129+
let summary_case_responses = interpolated_responses
130+
.iter()
131+
.filter(|sr| {
132+
let p = sr.path.get::<Profile>().unwrap();
133+
let s = sr.path.get::<Scenario>().unwrap();
134+
*p == profile && *s == scenario
135+
})
136+
.map(|sr| sr.series.iter().cloned())
137+
.collect();
138+
139+
let avg_vs_baseline = db::average(summary_case_responses)
140+
.map(|((c, d), i)| ((c, Some(d.expect("interpolated") / baseline)), i));
146141

147142
let graph_series = graph_series(avg_vs_baseline, graph_kind);
148143

0 commit comments

Comments
 (0)