Skip to content

Commit 536d52c

Browse files
committed
Add new summary table to compare page
1 parent 5c0b0a3 commit 536d52c

File tree

3 files changed

+164
-95
lines changed

3 files changed

+164
-95
lines changed

site/static/compare.html

Lines changed: 5 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -278,49 +278,16 @@ <h2>Comparing <span id="stat-header">{{stat}}</span> between <span id="before">{
278278
</fieldset>
279279
<p v-if="dataLoading && !data">Loading ...</p>
280280
<div v-if="data" id="content" style="margin-top: 15px">
281-
<div id="summary">
282-
<div style="display: flex; justify-content: end;">
281+
<div id="main-summary">
282+
<summary-table :cases="filteredSummary"></summary-table>
283+
<div style="position: absolute; right: 5px; top: 5px;">
283284
<span class="tooltip" style="margin-right: 1em;">?
284285
<span class="tooltiptext">
285-
The percents show arithmetic mean amongst regressions, amongst improvements
286-
and finally amongst all benchmarks in each category (all benchmarks or
287-
filtered benchmarks).
286+
The table shows summaries of regressions, improvements and all changes
287+
amongst the filtered benchmarks.
288288
</span>
289289
</span>
290290
</div>
291-
<div v-for="summaryPair in Object.entries(summary)" class="summary-container">
292-
<span style="font-weight: bold; margin-left: 5px; text-transform: capitalize;">{{
293-
summaryPair[0] }}:</span>
294-
<div class="summary-values">
295-
<span class="summary summary-wide positive">
296-
{{summaryPair[1].regressions.toString().padStart(3, "&nbsp;")}}
297-
<svg style="width:18px;height:18px" viewBox="0 0 24 24">
298-
<path
299-
d="M16,6L18.29,8.29L13.41,13.17L9.41,9.17L2,16.59L3.41,18L9.41,12L13.41,16L19.71,9.71L22,12V6H16Z">
300-
</path>
301-
</svg>
302-
&nbsp;(+{{(summaryPair[1].regressions_avg).toFixed(2)}}%)
303-
</span>
304-
<span class="summary">
305-
{{summaryPair[1].unchanged.toString().padStart(3, "&nbsp;")}}
306-
<svg style="width:18px;height:18px" viewBox="0 0 24 24">
307-
<path d="M22,12L18,8V11H3V13H18V16L22,12Z"></path>
308-
</svg>
309-
</span>
310-
<span class="summary summary-wide negative">
311-
{{summaryPair[1].improvements.toString().padStart(3, "&nbsp;")}}
312-
<svg style="width:18px;height:18px" viewBox="0 0 24 24">
313-
<path
314-
d="M16,18L18.29,15.71L13.41,10.83L9.41,14.83L2,7.41L3.41,6L9.41,12L13.41,8L19.71,14.29L22,12V18H16Z">
315-
</path>
316-
</svg>
317-
&nbsp;({{(summaryPair[1].improvements_avg).toFixed(2)}}%)
318-
</span>
319-
<span class="summary" v-bind:class="percentClass(summaryPair[1].average)">
320-
&nbsp;{{ signIfPositive(summaryPair[1].average) }}{{ (summaryPair[1].average).toFixed(2) }}%
321-
</span>
322-
</div>
323-
</div>
324291
</div>
325292
<div v-if="data.new_errors.length">
326293
<p><b>Newly broken benchmarks</b>:</p>

site/static/compare/script.js

Lines changed: 146 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -219,56 +219,9 @@ const app = Vue.createApp({
219219
stat() {
220220
return findQueryParam("stat") || "instructions:u";
221221
},
222-
summary() {
223-
// Create object with each test case that is not filtered out as a key
224-
const filtered = this.testCases.reduce((sum, next) => {
225-
sum[testCaseString(next)] = true;
226-
return sum;
227-
}, {});
228-
const newCount = {
229-
regressions: 0,
230-
regressions_avg: 0,
231-
improvements: 0,
232-
improvements_avg: 0,
233-
unchanged: 0,
234-
average: 0
235-
};
236-
237-
const addDatum = (result, datum, percent) => {
238-
if (percent > 0 && datum.is_relevant) {
239-
result.regressions += 1;
240-
result.regressions_avg += percent;
241-
} else if (percent < 0 && datum.is_relevant) {
242-
result.improvements += 1;
243-
result.improvements_avg += percent;
244-
} else {
245-
result.unchanged += 1;
246-
}
247-
result.average += percent;
248-
};
249-
250-
let result = {all: {...newCount}, filtered: {...newCount}}
251-
for (let d of this.data.comparisons) {
252-
const testCase = testCaseString(d)
253-
const datumA = d.statistics[0];
254-
const datumB = d.statistics[1];
255-
let percent = 100 * ((datumB - datumA) / datumA);
256-
addDatum(result.all, d, percent);
257-
if (filtered[testCase]) {
258-
addDatum(result.filtered, d, percent);
259-
}
260-
}
261-
262-
const computeAvg = (result) => {
263-
result.improvements_avg /= Math.max(result.improvements, 1);
264-
result.regressions_avg /= Math.max(result.regressions, 1);
265-
result.average /= Math.max(result.regressions + result.improvements + result.unchanged, 1);
266-
};
267-
computeAvg(result.all);
268-
computeAvg(result.filtered);
269-
270-
return result;
271-
222+
// Returns summary of currently filtered data
223+
filteredSummary() {
224+
return computeSummary(this.testCases);
272225
},
273226
benchmarkMap() {
274227
if (!this.data) return {};
@@ -289,12 +242,6 @@ const app = Vue.createApp({
289242
prLink(pr) {
290243
return `https://github.com/rust-lang/rust/pull/${pr}`;
291244
},
292-
signIfPositive(pct) {
293-
if (pct >= 0) {
294-
return "+";
295-
}
296-
return "";
297-
},
298245
diffClass(diff) {
299246
let klass = "";
300247
if (diff > 1) {
@@ -433,6 +380,77 @@ app.component('test-cases-table', {
433380
</div>
434381
`
435382
});
383+
384+
const SummaryPercentValue = {
385+
props: {
386+
value: Number,
387+
},
388+
template: `
389+
<span>{{ value.toFixed(2) }}%</span>
390+
`
391+
};
392+
const SummaryRange = {
393+
props: {
394+
range: Array,
395+
},
396+
template: `
397+
<div v-if="range.length > 0">
398+
[<SummaryPercentValue :value="range[0]" />, <SummaryPercentValue :value="range[1]" />]
399+
</div>
400+
<div v-else>-</div>
401+
`, components: {SummaryPercentValue}
402+
};
403+
const SummaryCount = {
404+
props: {
405+
cases: Number,
406+
benchmarks: Number
407+
},
408+
template: `
409+
<span :title="cases + ' test case(s), ' + benchmarks + ' unique benchmark(s)'">{{ cases }} ({{ benchmarks }})</span>
410+
`
411+
};
412+
413+
app.component('summary-table', {
414+
props: ['cases'],
415+
template: `
416+
<table class="summary-table">
417+
<thead>
418+
<th>Range</th>
419+
<th>Mean</th>
420+
<th>Count</th>
421+
<th><!-- icon --></th>
422+
</thead>
423+
<tbody>
424+
<tr class="positive">
425+
<td><SummaryRange :range="cases.regressions.range" /></td>
426+
<td><SummaryPercentValue :value="cases.regressions.average" /></td>
427+
<td><SummaryCount :cases="cases.regressions.count" :benchmarks="cases.regressions.benchmarks" /></td>
428+
<td>
429+
<svg style="width:16px;height:16px" viewBox="0 0 24 24">
430+
<path d="M16,6L18.29,8.29L13.41,13.17L9.41,9.17L2,16.59L3.41,18L9.41,12L13.41,16L19.71,9.71L22,12V6H16Z"></path>
431+
</svg>
432+
</td>
433+
</tr>
434+
<tr class="negative">
435+
<td><SummaryRange :range="cases.improvements.range" /></td>
436+
<td><SummaryPercentValue :value="cases.improvements.average" /></td>
437+
<td><SummaryCount :cases="cases.improvements.count" :benchmarks="cases.improvements.benchmarks" /></td>
438+
<td>
439+
<svg style="width:16px;height:16px" viewBox="0 0 24 24">
440+
<path d="M16,18L18.29,15.71L13.41,10.83L9.41,14.83L2,7.41L3.41,6L9.41,12L13.41,8L19.71,14.29L22,12V18H16Z"></path>
441+
</svg>
442+
</td>
443+
</tr>
444+
<tr>
445+
<td><SummaryRange :range="cases.all.range" /></td>
446+
<td><SummaryPercentValue :value="cases.all.average" /></td>
447+
<td><SummaryCount :cases="cases.all.count" :benchmarks="cases.all.benchmarks" /></td>
448+
</tr>
449+
</tbody>
450+
</table>
451+
`,
452+
components: {SummaryRange, SummaryPercentValue, SummaryCount}
453+
});
436454
app.mixin({
437455
methods: {
438456
percentClass(pct) {
@@ -448,6 +466,12 @@ app.mixin({
448466
}
449467
return klass;
450468
},
469+
signIfPositive(pct) {
470+
if (pct >= 0) {
471+
return "+";
472+
}
473+
return "";
474+
},
451475
}
452476
});
453477

@@ -470,6 +494,72 @@ function testCaseString(testCase) {
470494
return testCase.benchmark + "-" + testCase.profile + "-" + testCase.scenario;
471495
}
472496

497+
/**
498+
* Computes summaries of improvements, regressions and all changes from the given `comparisons`.
499+
* Returns a dictionary {improvements, regressions, all}.
500+
*/
501+
function computeSummary(testCases) {
502+
const regressions = {
503+
values: [],
504+
benchmarks: new Set(),
505+
};
506+
const improvements = {
507+
values: [],
508+
benchmarks: new Set(),
509+
};
510+
const all = {
511+
values: [],
512+
benchmarks: new Set(),
513+
};
514+
515+
const handleTestCase = (items, testCase) => {
516+
items.benchmarks.add(testCase.benchmark);
517+
items.values.push(testCase.percent);
518+
};
519+
520+
for (const testCase of testCases) {
521+
if (testCase.percent > 0) {
522+
handleTestCase(regressions, testCase);
523+
} else if (testCase.percent < 0) {
524+
handleTestCase(improvements, testCase);
525+
}
526+
handleTestCase(all, testCase);
527+
}
528+
529+
const computeSummary = (data) => {
530+
const values = data.values;
531+
const benchmarks = data.benchmarks;
532+
533+
const count = values.length;
534+
let range = [];
535+
if (count > 0) {
536+
range = [
537+
Math.min.apply(null, values),
538+
Math.max.apply(null, values),
539+
];
540+
if (Math.abs(range[0]) > Math.abs(range[1])) {
541+
range = [range[1], range[0]];
542+
}
543+
}
544+
545+
const sum = values.reduce((acc, item) => acc + item, 0);
546+
const average = sum / Math.max(count, 1);
547+
548+
return {
549+
count,
550+
benchmarks: benchmarks.size,
551+
average,
552+
range,
553+
}
554+
};
555+
556+
return {
557+
improvements: computeSummary(improvements),
558+
regressions: computeSummary(regressions),
559+
all: computeSummary(all)
560+
};
561+
}
562+
473563
function unique(arr) {
474564
return arr.filter((value, idx) => arr.indexOf(value) == idx);
475565
}

site/static/compare/style.css

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,10 +232,14 @@ input[type="checkbox"] {
232232
margin-top: 10px;
233233
}
234234

235-
#summary {
235+
#main-summary {
236236
border: 1px dashed;
237237
padding: 4px;
238238
border-radius: 6px;
239+
240+
display: flex;
241+
justify-content: center;
242+
position: relative;
239243
}
240244

241245
.summary-container {
@@ -296,3 +300,11 @@ input[type="checkbox"] {
296300
.quick-links .active {
297301
font-weight: bold;
298302
}
303+
304+
.summary-table th {
305+
text-align: center;
306+
}
307+
.summary-table td, .summary-table th {
308+
padding: 2px 5px;
309+
vertical-align: middle;
310+
}

0 commit comments

Comments
 (0)