Skip to content

Commit 096a4dc

Browse files
committed
Propagate runtime benchmark data from DB to the site comparison API
1 parent 0e2de9c commit 096a4dc

File tree

3 files changed

+123
-42
lines changed

3 files changed

+123
-42
lines changed

site/src/api.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ pub mod comparison {
167167
pub a: ArtifactDescription,
168168
pub b: ArtifactDescription,
169169
pub compile_comparisons: Vec<CompileBenchmarkComparison>,
170+
pub runtime_comparisons: Vec<RuntimeBenchmarkComparison>,
170171

171172
pub new_errors: Vec<(String, String)>,
172173

@@ -188,7 +189,7 @@ pub mod comparison {
188189
pub bootstrap_total: u64,
189190
}
190191

191-
/// A serializable wrapper for `comparison::ArtifactData`.
192+
/// A serializable wrapper for a comparison between two compile-time test results.
192193
#[derive(Debug, Clone, Serialize)]
193194
pub struct CompileBenchmarkComparison {
194195
pub benchmark: String,
@@ -199,6 +200,16 @@ pub mod comparison {
199200
pub significance_factor: f64,
200201
pub statistics: (f64, f64),
201202
}
203+
204+
/// A serializable wrapper for a comparison between two runtime test results.
205+
#[derive(Debug, Clone, Serialize)]
206+
pub struct RuntimeBenchmarkComparison {
207+
pub benchmark: String,
208+
pub is_relevant: bool,
209+
pub significance_threshold: f64,
210+
pub significance_factor: f64,
211+
pub statistics: (f64, f64),
212+
}
202213
}
203214

204215
pub mod status {

site/src/comparison.rs

Lines changed: 110 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ use crate::api;
66
use crate::db::{ArtifactId, Benchmark, Lookup, Profile, Scenario};
77
use crate::github;
88
use crate::load::SiteCtxt;
9-
use crate::selector::{self, BenchmarkQuery, CompileBenchmarkQuery, TestCase};
9+
use crate::selector::{
10+
self, BenchmarkQuery, CompileBenchmarkQuery, RuntimeBenchmarkQuery, TestCase,
11+
};
1012

1113
use collector::benchmark::category::Category;
1214
use collector::Bound;
@@ -153,6 +155,18 @@ pub async fn handle_compare(
153155
})
154156
.collect();
155157

158+
let runtime_comparisons = comparison
159+
.runtime_comparisons
160+
.into_iter()
161+
.map(|comparison| api::comparison::RuntimeBenchmarkComparison {
162+
benchmark: comparison.benchmark.to_string(),
163+
is_relevant: comparison.is_relevant(),
164+
significance_threshold: comparison.significance_threshold(),
165+
significance_factor: comparison.significance_factor(),
166+
statistics: comparison.results,
167+
})
168+
.collect();
169+
156170
let mut new_errors = comparison
157171
.newly_failed_benchmarks
158172
.into_iter()
@@ -163,6 +177,7 @@ pub async fn handle_compare(
163177
a: comparison.a.into(),
164178
b: comparison.b.into(),
165179
compile_comparisons,
180+
runtime_comparisons,
166181
new_errors,
167182
next,
168183
is_contiguous,
@@ -798,41 +813,38 @@ async fn compare_given_commits(
798813
let aids = Arc::new(vec![a.clone(), b.clone()]);
799814

800815
// get all crates, cache, and profile combinations for the given metric
801-
let query = CompileBenchmarkQuery::all_for_metric(metric);
802-
803-
// `responses` contains series iterators. The first element in the iterator is the data
804-
// for `a` and the second is the data for `b`
805-
let mut responses = ctxt.statistic_series(query.clone(), aids).await?;
806-
807-
let conn = ctxt.conn().await;
808-
let statistics_for_a = statistics_from_series(&mut responses);
809-
let statistics_for_b = statistics_from_series(&mut responses);
816+
let compile_comparisons = get_comparison::<CompileTestResultComparison, _, _>(
817+
ctxt,
818+
CompileBenchmarkQuery::all_for_metric(metric),
819+
a.clone(),
820+
aids.clone(),
821+
metric,
822+
master_commits,
823+
|test_case, comparison| CompileTestResultComparison {
824+
profile: test_case.profile,
825+
scenario: test_case.scenario,
826+
benchmark: test_case.benchmark,
827+
comparison,
828+
},
829+
)
830+
.await?;
810831

811-
let mut historical_data = HistoricalDataMap::<CompileBenchmarkQuery>::calculate(
832+
// get all crates, cache, and profile combinations for the given metric
833+
let runtime_comparisons = get_comparison::<RuntimeTestResultComparison, _, _>(
812834
ctxt,
835+
RuntimeBenchmarkQuery::all_for_metric(metric),
813836
a.clone(),
837+
aids,
838+
metric,
814839
master_commits,
815-
query,
840+
|test_case, comparison| RuntimeTestResultComparison {
841+
benchmark: test_case.benchmark,
842+
comparison,
843+
},
816844
)
817845
.await?;
818-
let comparisons = statistics_for_a
819-
.into_iter()
820-
.filter_map(|(test_case, a)| {
821-
statistics_for_b
822-
.get(&test_case)
823-
.map(|&b| CompileTestResultComparison {
824-
benchmark: test_case.benchmark,
825-
profile: test_case.profile,
826-
scenario: test_case.scenario,
827-
comparison: TestResultComparison {
828-
metric,
829-
historical_data: historical_data.data.remove(&test_case),
830-
results: (a, b),
831-
},
832-
})
833-
})
834-
.collect();
835846

847+
let conn = ctxt.conn().await;
836848
let mut errors_in_b = conn.get_error(b.lookup(&idx).unwrap()).await;
837849
let errors_in_a = conn.get_error(a.lookup(&idx).unwrap()).await;
838850
for (name, _) in errors_in_a {
@@ -842,11 +854,49 @@ async fn compare_given_commits(
842854
Ok(Some(ArtifactComparison {
843855
a: ArtifactDescription::for_artifact(&*conn, a.clone(), master_commits).await,
844856
b: ArtifactDescription::for_artifact(&*conn, b.clone(), master_commits).await,
845-
compile_comparisons: comparisons,
857+
compile_comparisons,
858+
runtime_comparisons,
846859
newly_failed_benchmarks: errors_in_b.into_iter().collect(),
847860
}))
848861
}
849862

863+
async fn get_comparison<
864+
Comparison: Eq + Hash,
865+
Query: BenchmarkQuery,
866+
F: Fn(Query::TestCase, TestResultComparison) -> Comparison,
867+
>(
868+
ctxt: &SiteCtxt,
869+
query: Query,
870+
start_artifact: ArtifactId,
871+
aids: Arc<Vec<ArtifactId>>,
872+
metric: Metric,
873+
master_commits: &[collector::MasterCommit],
874+
func: F,
875+
) -> Result<HashSet<Comparison>, BoxedError> {
876+
// `responses` contains series iterators. The first element in the iterator is the data
877+
// for `a` and the second is the data for `b`
878+
let mut responses = ctxt.statistic_series(query.clone(), aids).await?;
879+
880+
let statistics_for_a = statistics_from_series(&mut responses);
881+
let statistics_for_b = statistics_from_series(&mut responses);
882+
883+
let mut historical_data =
884+
HistoricalDataMap::<Query>::calculate(ctxt, start_artifact, master_commits, query).await?;
885+
Ok(statistics_for_a
886+
.into_iter()
887+
.filter_map(|(test_case, a)| {
888+
statistics_for_b.get(&test_case).map(|&b| {
889+
let comparison = TestResultComparison {
890+
metric,
891+
historical_data: historical_data.data.remove(&test_case),
892+
results: (a, b),
893+
};
894+
func(test_case, comparison)
895+
})
896+
})
897+
.collect())
898+
}
899+
850900
fn previous_commits(
851901
mut from: ArtifactId,
852902
n: usize,
@@ -989,6 +1039,8 @@ pub struct ArtifactComparison {
9891039
pub b: ArtifactDescription,
9901040
/// Compile test result comparisons between the two artifacts
9911041
pub compile_comparisons: HashSet<CompileTestResultComparison>,
1042+
/// Runtime test result copmarisons between the two artifacts
1043+
pub runtime_comparisons: HashSet<RuntimeTestResultComparison>,
9921044
/// A map from benchmark name to an error which occured when building `b` but not `a`.
9931045
pub newly_failed_benchmarks: HashMap<String, String>,
9941046
}
@@ -1355,6 +1407,34 @@ impl std::hash::Hash for CompileTestResultComparison {
13551407
}
13561408
}
13571409

1410+
#[derive(Debug, Clone)]
1411+
pub struct RuntimeTestResultComparison {
1412+
benchmark: Benchmark,
1413+
comparison: TestResultComparison,
1414+
}
1415+
1416+
impl Deref for RuntimeTestResultComparison {
1417+
type Target = TestResultComparison;
1418+
1419+
fn deref(&self) -> &Self::Target {
1420+
&self.comparison
1421+
}
1422+
}
1423+
1424+
impl cmp::PartialEq for RuntimeTestResultComparison {
1425+
fn eq(&self, other: &Self) -> bool {
1426+
self.benchmark == other.benchmark
1427+
}
1428+
}
1429+
1430+
impl cmp::Eq for RuntimeTestResultComparison {}
1431+
1432+
impl std::hash::Hash for RuntimeTestResultComparison {
1433+
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1434+
self.benchmark.hash(state);
1435+
}
1436+
}
1437+
13581438
// The direction of a performance change
13591439
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
13601440
pub enum Direction {

site/src/selector.rs

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ impl<TestCase, T> SeriesResponse<TestCase, T> {
181181
}
182182

183183
#[async_trait]
184-
pub trait BenchmarkQuery: Debug {
184+
pub trait BenchmarkQuery: Debug + Clone {
185185
type TestCase: TestCase;
186186

187187
async fn execute(
@@ -332,16 +332,6 @@ pub struct RuntimeBenchmarkQuery {
332332
}
333333

334334
impl RuntimeBenchmarkQuery {
335-
pub fn benchmark(mut self, selector: Selector<String>) -> Self {
336-
self.benchmark = selector;
337-
self
338-
}
339-
340-
pub fn metric(mut self, selector: Selector<Metric>) -> Self {
341-
self.metric = selector.map(|v| v.as_str().into());
342-
self
343-
}
344-
345335
pub fn all_for_metric(metric: Metric) -> Self {
346336
Self {
347337
benchmark: Selector::All,

0 commit comments

Comments
 (0)