Skip to content

Commit daea104

Browse files
committed
Add compare compile benchmark detail endpoint
1 parent 02dbc0b commit daea104

File tree

4 files changed

+127
-14
lines changed

4 files changed

+127
-14
lines changed

site/src/api.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,62 @@ pub mod graphs {
110110
}
111111
}
112112

113+
pub mod detail {
114+
use crate::api::graphs::{GraphKind, Series};
115+
use collector::Bound;
116+
use serde::de::{DeserializeOwned, Error};
117+
use serde::{Deserialize, Deserializer, Serialize};
118+
use std::fmt::Formatter;
119+
use std::marker::PhantomData;
120+
121+
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
122+
pub struct Request {
123+
pub start: Bound,
124+
pub end: Bound,
125+
pub stat: String,
126+
pub benchmark: String,
127+
pub scenario: String,
128+
pub profile: String,
129+
#[serde(deserialize_with = "vec_from_comma_separated")]
130+
pub kinds: Vec<GraphKind>,
131+
}
132+
133+
// Deserializes a comma separated list of GraphKind values
134+
fn vec_from_comma_separated<'de, T: DeserializeOwned, D>(
135+
deserializer: D,
136+
) -> Result<Vec<T>, D::Error>
137+
where
138+
D: Deserializer<'de>,
139+
{
140+
struct CommaSeparatedVisitor<T>(PhantomData<T>);
141+
142+
impl<'de, T: DeserializeOwned> serde::de::Visitor<'de> for CommaSeparatedVisitor<T> {
143+
type Value = Vec<T>;
144+
145+
fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
146+
formatter.write_str("comma separated list of GraphKind values")
147+
}
148+
149+
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
150+
where
151+
E: Error,
152+
{
153+
v.split(',')
154+
.map(|v| T::deserialize(serde::de::value::StrDeserializer::new(v)))
155+
.collect::<Result<Vec<T>, _>>()
156+
}
157+
}
158+
159+
deserializer.deserialize_str(CommaSeparatedVisitor(Default::default()))
160+
}
161+
162+
#[derive(Debug, PartialEq, Clone, Serialize)]
163+
pub struct Response {
164+
pub commits: Vec<(i64, String)>,
165+
pub graphs: Vec<Series>,
166+
}
167+
}
168+
113169
pub mod bootstrap {
114170
use collector::Bound;
115171
use hashbrown::HashMap;

site/src/request_handlers.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ mod status_page;
99
pub use bootstrap::handle_bootstrap;
1010
pub use dashboard::handle_dashboard;
1111
pub use github::handle_github;
12-
pub use graph::handle_graphs;
12+
pub use graph::{handle_compile_detail, handle_graphs};
1313
pub use next_artifact::handle_next_artifact;
1414
pub use self_profile::{
1515
handle_self_profile, handle_self_profile_processed_download, handle_self_profile_raw,

site/src/request_handlers/graph.rs

Lines changed: 62 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,57 @@ use std::collections::HashMap;
33
use std::sync::Arc;
44

55
use crate::api::graphs::GraphKind;
6-
use crate::api::{graphs, ServerResult};
6+
use crate::api::{detail, graphs, ServerResult};
77
use crate::db::{self, ArtifactId, Profile, Scenario};
88
use crate::interpolate::IsInterpolated;
99
use crate::load::SiteCtxt;
1010
use crate::selector::{CompileBenchmarkQuery, CompileTestCase, Selector, SeriesResponse};
1111

12+
/// Returns data for a detailed information when comparing a single test result comparison
13+
/// for a compile-time benchmark.
14+
pub async fn handle_compile_detail(
15+
request: detail::Request,
16+
ctxt: Arc<SiteCtxt>,
17+
) -> ServerResult<detail::Response> {
18+
log::info!("handle_compile_detail({:?})", request);
19+
20+
let artifact_ids = Arc::new(master_artifact_ids_for_range(
21+
&ctxt,
22+
request.start,
23+
request.end,
24+
));
25+
26+
let interpolated_responses: Vec<_> = ctxt
27+
.statistic_series(
28+
CompileBenchmarkQuery::default()
29+
.benchmark(Selector::One(request.benchmark))
30+
.profile(Selector::One(request.profile.parse()?))
31+
.scenario(Selector::One(request.scenario.parse()?))
32+
.metric(Selector::One(request.stat.parse()?)),
33+
artifact_ids.clone(),
34+
)
35+
.await?
36+
.into_iter()
37+
.map(|sr| sr.interpolate().map(|series| series.collect::<Vec<_>>()))
38+
.collect();
39+
40+
let mut graphs = Vec::new();
41+
42+
let mut interpolated_responses = interpolated_responses.into_iter();
43+
if let Some(response) = interpolated_responses.next() {
44+
let series = response.series.into_iter().collect::<Vec<_>>();
45+
for kind in request.kinds {
46+
graphs.push(graph_series(series.clone().into_iter(), kind));
47+
}
48+
}
49+
assert!(interpolated_responses.next().is_none());
50+
51+
Ok(detail::Response {
52+
commits: artifact_ids_to_commits(artifact_ids),
53+
graphs,
54+
})
55+
}
56+
1257
pub async fn handle_graphs(
1358
request: graphs::Request,
1459
ctxt: Arc<SiteCtxt>,
@@ -33,7 +78,7 @@ pub async fn handle_graphs(
3378
}
3479
}
3580

36-
let resp = create_graphs(request, &ctxt).await?;
81+
let resp = Arc::new(create_graphs(request, &ctxt).await?);
3782

3883
if is_default_query {
3984
ctxt.landing_page.store(Arc::new(Some(resp.clone())));
@@ -45,7 +90,7 @@ pub async fn handle_graphs(
4590
async fn create_graphs(
4691
request: graphs::Request,
4792
ctxt: &SiteCtxt,
48-
) -> ServerResult<Arc<graphs::Response>> {
93+
) -> ServerResult<graphs::Response> {
4994
let artifact_ids = Arc::new(master_artifact_ids_for_range(
5095
ctxt,
5196
request.start,
@@ -98,17 +143,21 @@ async fn create_graphs(
98143
.insert(scenario, graph_series);
99144
}
100145

101-
Ok(Arc::new(graphs::Response {
102-
commits: Arc::try_unwrap(artifact_ids)
103-
.unwrap()
104-
.into_iter()
105-
.map(|c| match c {
106-
ArtifactId::Commit(c) => (c.date.0.timestamp(), c.sha),
107-
ArtifactId::Tag(_) => unreachable!(),
108-
})
109-
.collect(),
146+
Ok(graphs::Response {
147+
commits: artifact_ids_to_commits(artifact_ids),
110148
benchmarks,
111-
}))
149+
})
150+
}
151+
152+
fn artifact_ids_to_commits(artifact_ids: Arc<Vec<ArtifactId>>) -> Vec<(i64, String)> {
153+
Arc::try_unwrap(artifact_ids)
154+
.unwrap()
155+
.into_iter()
156+
.map(|c| match c {
157+
ArtifactId::Commit(c) => (c.date.0.timestamp(), c.sha),
158+
ArtifactId::Tag(_) => unreachable!(),
159+
})
160+
.collect()
112161
}
113162

114163
/// Returns master commit artifact IDs for the given range.

site/src/server.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,14 @@ async fn serve_req(server: Server, req: Request) -> Result<Response, ServerError
375375
crate::comparison::handle_triage(input, &ctxt).await,
376376
));
377377
}
378+
"/perf/compare-compile-detail" => {
379+
let query = check!(parse_query_string(req.uri()));
380+
return server
381+
.handle_fallible_get_async(&req, &compression, |c| {
382+
request_handlers::handle_compile_detail(query, c)
383+
})
384+
.await;
385+
}
378386
"/perf/graphs" => {
379387
let query = check!(parse_query_string(req.uri()));
380388
return server

0 commit comments

Comments
 (0)