Skip to content

Commit 493da4f

Browse files
Implement summary graphs.
Adds two graphs for release and debug modes. The current series are the clean, initial incremental, incremental clean, and println patch. Values are multiples of the first shown clean non-incremental build. Future work will involve adding more lines to the graph, but currently there's no other similar patch like "println" that would be trivial to add.
1 parent 6ce7f5e commit 493da4f

File tree

4 files changed

+123
-31
lines changed

4 files changed

+123
-31
lines changed

collector/src/lib.rs

+39-11
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ impl Ord for Commit {
5151
}
5252
}
5353

54-
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
54+
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, Hash)]
5555
pub struct Patch {
5656
index: usize,
5757
name: String,
@@ -99,14 +99,43 @@ impl Patch {
9999
}
100100

101101

102-
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
102+
#[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize, Serialize)]
103103
pub enum BenchmarkState {
104104
Clean,
105105
IncrementalStart,
106106
IncrementalClean,
107107
IncrementalPatched(Patch),
108108
}
109109

110+
impl BenchmarkState {
111+
pub fn is_base_compile(&self) -> bool {
112+
if let BenchmarkState::Clean = *self {
113+
true
114+
} else {
115+
false
116+
}
117+
}
118+
119+
pub fn is_patch(&self) -> bool {
120+
if let BenchmarkState::IncrementalPatched(_) = *self {
121+
true
122+
} else {
123+
false
124+
}
125+
}
126+
127+
pub fn name(&self) -> String {
128+
match *self {
129+
BenchmarkState::Clean => format!("clean"),
130+
BenchmarkState::IncrementalStart => format!("baseline incremental"),
131+
BenchmarkState::IncrementalClean => format!("clean incremental"),
132+
BenchmarkState::IncrementalPatched(ref patch) => {
133+
format!("patched incremental: {}", patch.name)
134+
}
135+
}
136+
}
137+
}
138+
110139
#[derive(Debug, Clone, Deserialize, Serialize)]
111140
pub struct Benchmark {
112141
pub runs: Vec<Run>,
@@ -127,21 +156,20 @@ pub struct Run {
127156
}
128157

129158
impl Run {
159+
pub fn is_trivial(&self) -> bool {
160+
if let BenchmarkState::IncrementalPatched(ref patch) = self.state {
161+
return patch.name == "println";
162+
}
163+
false
164+
}
165+
130166
pub fn name(&self) -> String {
131-
let base = match self.state {
132-
BenchmarkState::Clean => format!("clean"),
133-
BenchmarkState::IncrementalStart => format!("baseline incremental"),
134-
BenchmarkState::IncrementalClean => format!("clean incremental"),
135-
BenchmarkState::IncrementalPatched(ref patch) => {
136-
format!("patched incremental: {}", patch.name)
137-
}
138-
};
139167
let opt = if self.release {
140168
"-opt"
141169
} else {
142170
""
143171
};
144-
base + opt
172+
self.state.name() + opt
145173
}
146174

147175
pub fn get_stat(&self, stat: &str) -> Option<f64> {

site/src/api.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,10 @@ pub mod graph {
111111
}
112112

113113
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
114-
/// Crate -> Benchmark -> [GraphData]
115-
pub struct Response(pub HashMap<String, HashMap<String, Vec<GraphData>>>);
114+
pub struct Response {
115+
/// Crate -> Benchmark -> [GraphData]
116+
pub benchmarks: HashMap<String, HashMap<String, Vec<GraphData>>>,
117+
}
116118
}
117119

118120
pub mod days {

site/src/server.rs

+65-3
Original file line numberDiff line numberDiff line change
@@ -103,12 +103,23 @@ pub fn handle_graph(body: graph::Request, data: &InputData) -> ServerResult<grap
103103
let mut result = HashMap::with_capacity(data.crate_list.len() * 2);
104104
let elements = out.len();
105105
let mut last_commit = None;
106+
let mut initial_base_compile = None;
107+
let mut initial_release_base_compile = None;
106108
for date_data in out {
107109
let commit = date_data.commit;
110+
let mut summary_points = HashMap::new();
108111
for (name, runs) in date_data.data {
109-
let mut entry = result.entry(name)
112+
let mut entry = result.entry(name.clone())
110113
.or_insert_with(|| HashMap::with_capacity(runs.len()));
111-
for (name, _, value) in runs {
114+
let mut base_compile = false;
115+
let mut trivial = false;
116+
for (name, run, value) in runs.clone() {
117+
if run.state.is_base_compile() {
118+
base_compile = true;
119+
} else if run.is_trivial() {
120+
trivial = true;
121+
}
122+
112123
let mut entry = entry.entry(name.clone())
113124
.or_insert_with(|| Vec::<graph::GraphData>::with_capacity(elements));
114125
let first = entry.first().map(|d| d.absolute);
@@ -130,11 +141,62 @@ pub fn handle_graph(body: graph::Request, data: &InputData) -> ServerResult<grap
130141
x: date_data.date.0.timestamp() as u64, // all dates are since 1970
131142
});
132143
}
144+
if base_compile && trivial {
145+
for (_, run, value) in runs {
146+
// TODO: Come up with a way to summarize non-standard patches
147+
if run.state.is_patch() && !run.is_trivial() {
148+
continue;
149+
}
150+
summary_points.entry((run.release, run.state))
151+
.or_insert_with(Vec::new)
152+
.push(value);
153+
}
154+
}
155+
}
156+
for (&(release, ref state), values) in &summary_points {
157+
let value = values.iter().sum::<f64>() / (values.len() as f64);
158+
if !release && state.is_base_compile() && initial_base_compile.is_none() {
159+
initial_base_compile = Some(value);
160+
}
161+
if release && state.is_base_compile() && initial_release_base_compile.is_none() {
162+
initial_release_base_compile = Some(value);
163+
}
164+
}
165+
for ((release, state), values) in summary_points {
166+
let summary = result.entry(String::from("Summary") + if release { "-opt" } else {""})
167+
.or_insert_with(HashMap::new);
168+
let entry = summary.entry(state.name()).or_insert_with(Vec::new);
169+
let value = values.iter().sum::<f64>() / (values.len() as f64);
170+
let value = value / if release {
171+
initial_release_base_compile.unwrap()
172+
} else {
173+
initial_base_compile.unwrap()
174+
};
175+
let first = entry.first().map(|d: &graph::GraphData| d.absolute);
176+
let percent = first.map_or(0.0, |f| (value - f) / f * 100.0);
177+
let url = last_commit.as_ref().map(|c| {
178+
format!("/compare.html?start={}&end={}&stat={}",
179+
c,
180+
commit,
181+
body.stat,
182+
)
183+
});
184+
entry.push(graph::GraphData {
185+
benchmark: state.name(),
186+
commit: commit.clone(),
187+
url: url,
188+
absolute: value,
189+
percent: percent,
190+
y: if body.absolute { value } else { percent },
191+
x: date_data.date.0.timestamp() as u64, // all dates are since 1970
192+
});
133193
}
134194
last_commit = Some(commit);
135195
}
136196

137-
Ok(graph::Response(result))
197+
Ok(graph::Response {
198+
benchmarks: result,
199+
})
138200
}
139201

140202
pub fn handle_data(body: data::Request, data: &InputData) -> ServerResult<data::Response> {

site/static/index.html

+15-15
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@
2222
<script src="shared.js"></script>
2323

2424
<script>
25+
let summaryYAxis = "Multiplier of baseline non-incr";
2526
function init_graph(response, stat, absolute) {
26-
let sorted_names = Object.keys(response);
27+
let sorted_names = Object.keys(response.benchmarks);
2728
sorted_names.sort();
2829
document.getElementById("charts").style.display = "none";
2930
let title = "";
@@ -54,16 +55,6 @@
5455
return false;
5556
}
5657

57-
function formatter() {
58-
let date = new Date();
59-
date.setUTCMilliseconds(this.x);
60-
let commit = this.point.commit.substr(0, 10);
61-
return "<b>" + date.toLocaleString() + " - " + commit + "</b>" +
62-
"<br>" + this.series.name + ": " + this.point.absolute.toFixed(2) + " " +
63-
yAxis.toLowerCase() + " (" +
64-
this.point.percent.toFixed(2) + "% from start)";
65-
}
66-
6758
let elements = [];
6859
for (let crate_name of sorted_names) {
6960
let element = document.createElement("div");
@@ -73,11 +64,11 @@
7364
let graphs = [];
7465
for (let crate_name of sorted_names) {
7566
graphs.push(() => {
76-
let benchmark_names = Object.keys(response[crate_name]);
67+
let benchmark_names = Object.keys(response.benchmarks[crate_name]);
7768
benchmark_names.sort();
7869
let datasets = [];
7970
for (let name of benchmark_names) {
80-
let data = response[crate_name][name];
71+
let data = response.benchmarks[crate_name][name];
8172
datasets.push({
8273
name: data[0].benchmark,
8374
animation: false,
@@ -106,14 +97,23 @@
10697
series: datasets,
10798
tooltip: {
10899
crosshairs: [true],
109-
formatter: formatter,
100+
formatter: function formatter() {
101+
let date = new Date();
102+
date.setUTCMilliseconds(this.x);
103+
let commit = this.point.commit.substr(0, 10);
104+
let yAxis = crate_name.startsWith("Summary") ? summaryYAxis : yAxis;
105+
return "<b>" + date.toLocaleString() + " - " + commit + "</b>" +
106+
"<br>" + this.series.name + ": " + this.point.absolute.toFixed(2) + " " +
107+
yAxis.toLowerCase() + " (" +
108+
this.point.percent.toFixed(2) + "% from start)";
109+
},
110110
},
111111
xAxis: {
112112
type: "datetime",
113113
},
114114
yAxis: absolute ? {
115115
title: {
116-
text: yAxis,
116+
text: crate_name.startsWith("Summary") ? summaryYAxis : yAxis,
117117
},
118118
min: 0,
119119
} : {

0 commit comments

Comments
 (0)