Skip to content

Commit 02a1c90

Browse files
authored
Merge pull request #1922 from s7tya/add-runtime-detail-graphs-api
Add runtime detail graphs api
2 parents 2f18ecf + cd747c1 commit 02a1c90

22 files changed

+1107
-474
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<script setup lang="ts">
2+
import {computed} from "vue";
3+
import {useExpandedStore} from "../utils/expansion";
4+
5+
const props = defineProps<{
6+
id: string;
7+
}>();
8+
9+
const {toggleExpanded, isExpanded} = useExpandedStore();
10+
11+
const expanded = computed(() => isExpanded(props.id));
12+
</script>
13+
14+
<template>
15+
<tr
16+
@click="toggleExpanded(props.id)"
17+
:class="{toggle: true, toggled: expanded}"
18+
>
19+
<td class="toggle-arrow">
20+
{{ expanded ? "▼" : "▶" }}
21+
</td>
22+
<slot name="default" />
23+
</tr>
24+
<tr v-if="expanded">
25+
<slot name="expanded" />
26+
</tr>
27+
</template>
28+
29+
<style lang="scss" scoped>
30+
.toggle {
31+
cursor: pointer;
32+
33+
.toggle-arrow {
34+
padding-right: 5px;
35+
}
36+
37+
&:hover,
38+
&.toggled {
39+
background-color: #d6d3d35c;
40+
}
41+
}
42+
</style>

site/frontend/src/graph/api.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
import {GraphData, GraphsSelector} from "./data";
1+
import {CompileGraphData, GraphsSelector} from "./data";
22
import {getJson} from "../utils/requests";
33
import {GRAPH_DATA_URL} from "../urls";
44

5-
export async function loadGraphs(selector: GraphsSelector): Promise<GraphData> {
5+
export async function loadGraphs(
6+
selector: GraphsSelector
7+
): Promise<CompileGraphData> {
68
const params = {
79
start: selector.start,
810
end: selector.end,
@@ -12,5 +14,5 @@ export async function loadGraphs(selector: GraphsSelector): Promise<GraphData> {
1214
scenario: selector.scenario,
1315
profile: selector.profile,
1416
};
15-
return await getJson<GraphData>(GRAPH_DATA_URL, params);
17+
return await getJson<CompileGraphData>(GRAPH_DATA_URL, params);
1618
}

site/frontend/src/graph/data.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,14 @@ export interface Series {
1717
}
1818

1919
// Graph data received from the server
20-
export interface GraphData {
20+
export interface CompileGraphData {
2121
commits: Array<[number, string]>;
2222
// benchmark -> profile -> scenario -> series
2323
benchmarks: Dict<Dict<Dict<Series>>>;
2424
}
25+
26+
export interface RuntimeGraphData {
27+
commits: Array<[number, string]>;
28+
// benchmark -> series
29+
benchmarks: Dict<Series>;
30+
}

site/frontend/src/graph/render.ts

Lines changed: 152 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import uPlot, {TypedArray} from "uplot";
2-
import {GraphData, GraphsSelector} from "./data";
2+
import {CompileGraphData, GraphsSelector, RuntimeGraphData} from "./data";
33

44
const commonCacheStateColors = {
55
full: "#7cb5ec",
@@ -374,7 +374,7 @@ function genPlotOpts({
374374
};
375375
}
376376

377-
function normalizeData(data: GraphData) {
377+
function normalizeData(data: CompileGraphData) {
378378
function optInterpolated(profile) {
379379
for (const scenario in profile) {
380380
profile[scenario].interpolated_indices = new Set(
@@ -409,7 +409,7 @@ export type GraphRenderOpts = {
409409
// Renders the plots data with the given parameters from the `selector` into
410410
// the passed DOM element.
411411
export function renderPlots(
412-
data: GraphData,
412+
data: CompileGraphData,
413413
selector: GraphsSelector,
414414
plotElement: HTMLElement,
415415
opts: GraphRenderOpts
@@ -420,41 +420,50 @@ export function renderPlots(
420420

421421
normalizeData(data);
422422

423-
const names = Object.keys(data.benchmarks).sort();
423+
const benchNames = Object.keys(data.benchmarks).sort();
424424

425-
for (const benchName of names) {
426-
let benchKinds = data.benchmarks[benchName];
425+
for (const benchName of benchNames) {
426+
let profiles = data.benchmarks[benchName];
427427

428428
let i = 0;
429429

430-
for (let benchKind in benchKinds) {
431-
let cacheStates = benchKinds[benchKind];
432-
let cacheStateNames = Object.keys(cacheStates);
433-
cacheStateNames.sort();
430+
for (let profile in profiles) {
431+
let scenarios = profiles[profile];
432+
let scenarioNames = Object.keys(scenarios);
433+
scenarioNames.sort();
434434

435435
let yAxis = selector.stat;
436436
let yAxisUnit = null;
437-
if (selector.stat == "instructions:u") {
438-
yAxis = "CPU instructions";
439-
yAxisUnit = "count";
440-
} else if (selector.stat == "cycles:u") {
441-
yAxis = "CPU cycles";
442-
yAxisUnit = "count";
443-
} else if (selector.stat == "cpu-clock") {
444-
yAxis = "CPU clock";
445-
yAxisUnit = "seconds";
446-
} else if (selector.stat == "task-clock") {
447-
yAxis = "Task clock";
448-
yAxisUnit = "seconds";
449-
} else if (selector.stat == "wall-time") {
450-
yAxis = "Wall time";
451-
yAxisUnit = "seconds";
452-
} else if (selector.stat == "max-rss") {
453-
yAxis = "Maximum resident set size";
454-
yAxisUnit = "kB";
455-
} else if (selector.stat == "faults") {
456-
yAxis = "Faults";
457-
yAxisUnit = "count";
437+
438+
switch (selector.stat) {
439+
case "instructions:u":
440+
yAxis = "CPU instructions";
441+
yAxisUnit = "count";
442+
break;
443+
case "cycles:u":
444+
yAxis = "CPU cycles";
445+
yAxisUnit = "count";
446+
break;
447+
case "cpu-clock":
448+
yAxis = "CPU clock";
449+
yAxisUnit = "seconds";
450+
break;
451+
case "task-clock":
452+
yAxis = "Task clock";
453+
yAxisUnit = "seconds";
454+
break;
455+
case "wall-time":
456+
yAxis = "Wall time";
457+
yAxisUnit = "seconds";
458+
break;
459+
case "max-rss":
460+
yAxis = "Maximum resident set size";
461+
yAxisUnit = "kB";
462+
break;
463+
case "faults":
464+
yAxis = "Faults";
465+
yAxisUnit = "count";
466+
break;
458467
}
459468

460469
if (selector.kind == "raw" && benchName == "Summary") {
@@ -476,23 +485,22 @@ export function renderPlots(
476485

477486
let otherColorIdx = 0;
478487

479-
for (let cacheState of cacheStateNames) {
480-
let yVals = cacheStates[cacheState].points;
488+
for (let scenarioName of scenarioNames) {
489+
let yVals = scenarios[scenarioName].points;
481490
let color =
482-
commonCacheStateColors[cacheState] ||
491+
commonCacheStateColors[scenarioName] ||
483492
otherCacheStateColors[otherColorIdx++];
484493

485494
plotData.push(yVals);
486495

487496
seriesOpts.push({
488-
label: cacheState,
497+
label: scenarioName,
489498
width: devicePixelRatio,
490499
stroke: color,
491500
});
492501
}
493502

494-
let indices =
495-
cacheStates[Object.keys(cacheStates)[0]].interpolated_indices;
503+
let indices = scenarios[Object.keys(scenarios)[0]].interpolated_indices;
496504

497505
let plotOpts = genPlotOpts({
498506
width,
@@ -501,14 +509,14 @@ export function renderPlots(
501509
series: seriesOpts,
502510
commits: data.commits,
503511
stat: selector.stat,
504-
isInterpolated(dataIdx) {
512+
isInterpolated(dataIdx: number) {
505513
return indices.has(dataIdx);
506514
},
507515
absoluteMode: selector.kind == "raw",
508516
hooks,
509517
});
510518
if (renderTitle) {
511-
plotOpts["title"] = `${benchName}-${benchKind}`;
519+
plotOpts["title"] = `${benchName}-${profile}`;
512520
}
513521

514522
new uPlot(plotOpts, plotData as any as TypedArray[], plotElement);
@@ -517,3 +525,108 @@ export function renderPlots(
517525
}
518526
}
519527
}
528+
529+
export function renderRuntimePlots(
530+
data: RuntimeGraphData,
531+
selector: GraphsSelector,
532+
plotElement: HTMLElement,
533+
opts: GraphRenderOpts
534+
) {
535+
const renderTitle = opts.renderTitle ?? true;
536+
const hooks = opts.hooks ?? {};
537+
const width = opts.width;
538+
539+
const benchNames = Object.keys(data.benchmarks).sort();
540+
541+
for (const benchName of benchNames) {
542+
const benchmark = data.benchmarks[benchName];
543+
let i = 0;
544+
545+
let yAxis = selector.stat;
546+
let yAxisUnit = null;
547+
548+
switch (selector.stat) {
549+
case "instructions:u":
550+
yAxis = "CPU instructions";
551+
yAxisUnit = "count";
552+
break;
553+
case "cycles:u":
554+
yAxis = "CPU cycles";
555+
yAxisUnit = "count";
556+
break;
557+
case "cpu-clock":
558+
yAxis = "CPU clock";
559+
yAxisUnit = "seconds";
560+
break;
561+
case "task-clock":
562+
yAxis = "Task clock";
563+
yAxisUnit = "seconds";
564+
break;
565+
case "wall-time":
566+
yAxis = "Wall time";
567+
yAxisUnit = "seconds";
568+
break;
569+
case "max-rss":
570+
yAxis = "Maximum resident set size";
571+
yAxisUnit = "kB";
572+
break;
573+
case "faults":
574+
yAxis = "Faults";
575+
yAxisUnit = "count";
576+
break;
577+
}
578+
579+
if (selector.kind == "raw" && benchName == "Summary") {
580+
yAxisUnit = "relative";
581+
} else if (selector.kind == "percentfromfirst") {
582+
yAxisUnit = "% change from first";
583+
} else if (selector.kind == "percentrelative") {
584+
yAxisUnit = "% change from previous";
585+
}
586+
587+
yAxis = yAxisUnit ? `${yAxis} (${yAxisUnit})` : yAxis;
588+
let yAxisLabel = i == 0 ? yAxis : null;
589+
590+
let seriesOpts = [{}];
591+
592+
let xVals = data.commits.map((c) => c[0]);
593+
594+
let plotData = [xVals];
595+
596+
let otherColorIdx = 0;
597+
598+
let yVals = benchmark.points;
599+
let color = otherCacheStateColors[otherColorIdx++];
600+
601+
plotData.push(yVals);
602+
603+
seriesOpts.push({
604+
label: benchName,
605+
width: devicePixelRatio,
606+
stroke: color,
607+
});
608+
609+
let indices = new Set(benchmark.interpolated_indices);
610+
611+
let plotOpts = genPlotOpts({
612+
width,
613+
height: 300,
614+
yAxisLabel,
615+
series: seriesOpts,
616+
commits: data.commits,
617+
stat: selector.stat,
618+
isInterpolated(dataIdx: number) {
619+
return indices.has(dataIdx);
620+
},
621+
absoluteMode: selector.kind == "raw",
622+
hooks,
623+
});
624+
if (renderTitle) {
625+
plotOpts["title"] = `${benchName}`;
626+
}
627+
628+
new uPlot(plotOpts, plotData as any as TypedArray[], plotElement);
629+
630+
i++;
631+
}
632+
}

site/frontend/src/pages/compare/compile/common.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,3 +204,7 @@ export function createCompileBenchmarkMap(
204204
}
205205
return benchmarks;
206206
}
207+
208+
export function testCaseKey(testCase: CompileTestCase): string {
209+
return `${testCase.benchmark};${testCase.profile};${testCase.scenario};${testCase.category}`;
210+
}

0 commit comments

Comments
 (0)