Skip to content

Commit 7a5d761

Browse files
committed
Refactor detail loading
1 parent 31520c1 commit 7a5d761

File tree

4 files changed

+45
-30
lines changed

4 files changed

+45
-30
lines changed

site/frontend/src/pages/compare/compile/table/benchmark-detail.vue

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {GraphRenderOpts, renderPlots} from "../../../../graph/render";
1313
import {GraphData, GraphKind, GraphsSelector} from "../../../../graph/data";
1414
import uPlot from "uplot";
1515
import CachegrindCmd from "../../../../components/cachegrind-cmd.vue";
16-
import {COMPILE_DETAIL_RESOLVER} from "./detail-resolver";
16+
import {COMPILE_DETAIL_GRAPHS_RESOLVER} from "./detail-resolver";
1717
import PerfettoLink from "../../../../components/perfetto-link.vue";
1818
1919
const props = defineProps<{
@@ -109,8 +109,8 @@ async function renderGraphs() {
109109
end,
110110
kinds: ["percentrelative", "raw"] as GraphKind[],
111111
};
112-
const detail = await COMPILE_DETAIL_RESOLVER.loadDetail(selector);
113-
if (detail.commits.length === 0) {
112+
const graphsDetail = await COMPILE_DETAIL_GRAPHS_RESOLVER.load(selector);
113+
if (graphsDetail.commits.length === 0) {
114114
return;
115115
}
116116
@@ -119,13 +119,13 @@ async function renderGraphs() {
119119
kind: GraphKind
120120
): [GraphData, GraphsSelector] {
121121
const data = {
122-
commits: detail.commits,
122+
commits: graphsDetail.commits,
123123
benchmarks: {
124124
[selector.benchmark]: {
125125
// The server returns profiles capitalized, so we need to match that
126126
// here, so that the graph code can find the expected profile.
127127
[capitalize(selector.profile)]: {
128-
[selector.scenario]: detail.graphs[index],
128+
[selector.scenario]: graphsDetail.graphs[index],
129129
},
130130
},
131131
},
Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import {GraphKind, Series} from "../../../../graph/data";
22
import {getJson} from "../../../../utils/requests";
3-
import {COMPARE_COMPILE_DETAIL_DATA_URL} from "../../../../urls";
3+
import {COMPARE_COMPILE_DETAIL_GRAPHS_DATA_URL} from "../../../../urls";
4+
import {CachedDataLoader} from "./utils";
45

5-
export interface CompileDetailSelector {
6+
export interface CompileDetailGraphsSelector {
67
start: string;
78
end: string;
89
stat: string;
@@ -13,7 +14,7 @@ export interface CompileDetailSelector {
1314
}
1415

1516
// Compile benchmark detail received from the server
16-
export interface CompileDetail {
17+
export interface CompileDetailGraphs {
1718
commits: Array<[number, string]>;
1819
// One Series for each GraphKind in the CompileDetailSelector
1920
graphs: Series[];
@@ -24,33 +25,23 @@ export interface CompileDetail {
2425
* This is important for Vue components that download the benchmark detail on mount.
2526
* Without a cache, they would download the detail each time they are destroyed
2627
* and recreated.
27-
*/
28-
export class CompileBenchmarkDetailResolver {
29-
private cache: Dict<CompileDetail> = {};
30-
31-
public async loadDetail(
32-
selector: CompileDetailSelector
33-
): Promise<CompileDetail> {
34-
const key = `${selector.benchmark};${selector.profile};${selector.scenario};${selector.start};${selector.end};${selector.stat};${selector.kinds}`;
35-
if (!this.cache.hasOwnProperty(key)) {
36-
this.cache[key] = await loadDetail(selector);
37-
}
38-
39-
return this.cache[key];
40-
}
41-
}
42-
43-
/**
4428
* This is essentially a global variable, but it makes the code simpler and
4529
* since we currently don't have any unit tests, we don't really need to avoid
4630
* global variables that much. If needed, it could be provided to Vue components
4731
* from a parent via props or context.
4832
*/
49-
export const COMPILE_DETAIL_RESOLVER = new CompileBenchmarkDetailResolver();
33+
export const COMPILE_DETAIL_GRAPHS_RESOLVER: CachedDataLoader<
34+
CompileDetailGraphsSelector,
35+
CompileDetailGraphs
36+
> = new CachedDataLoader(
37+
(key: CompileDetailGraphsSelector) =>
38+
`${key.benchmark};${key.profile};${key.scenario};${key.start};${key.end};${key.stat};${key.kinds}`,
39+
loadDetail
40+
);
5041

5142
async function loadDetail(
52-
selector: CompileDetailSelector
53-
): Promise<CompileDetail> {
43+
selector: CompileDetailGraphsSelector
44+
): Promise<CompileDetailGraphs> {
5445
const params = {
5546
start: selector.start,
5647
end: selector.end,
@@ -60,5 +51,8 @@ async function loadDetail(
6051
profile: selector.profile,
6152
kinds: selector.kinds.join(","),
6253
};
63-
return await getJson<CompileDetail>(COMPARE_COMPILE_DETAIL_DATA_URL, params);
54+
return await getJson<CompileDetailGraphs>(
55+
COMPARE_COMPILE_DETAIL_GRAPHS_DATA_URL,
56+
params
57+
);
6458
}

site/frontend/src/pages/compare/compile/table/utils.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,24 @@ function format_ymd(date: Date): string {
2929
export function daysBetweenDates(a: Date, b: Date): number {
3030
return Math.floor((b.getTime() - a.getTime()) / (1000 * 60 * 60 * 24));
3131
}
32+
33+
/**
34+
* Provides a cache for `Output` items that can be loaded asynchronously, given a certain `Key`.
35+
* If a value has already been loaded for the same key, it will be resolved from the cache.
36+
*/
37+
export class CachedDataLoader<Key, Output> {
38+
private cache: Dict<Output> = {};
39+
40+
constructor(
41+
private key_to_hash: (key: Key) => string,
42+
private load_fn: (key: Key) => Promise<Output>
43+
) {}
44+
45+
public async load(key: Key): Promise<Output> {
46+
const hash = this.key_to_hash(key);
47+
if (!this.cache.hasOwnProperty(hash)) {
48+
this.cache[hash] = await this.load_fn(key);
49+
}
50+
return this.cache[hash];
51+
}
52+
}

site/frontend/src/urls.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@ export const STATUS_DATA_URL = `${BASE_URL}/status_page`;
77
export const BOOTSTRAP_DATA_URL = `${BASE_URL}/bootstrap`;
88
export const GRAPH_DATA_URL = `${BASE_URL}/graphs`;
99
export const COMPARE_DATA_URL = `${BASE_URL}/get`;
10-
export const COMPARE_COMPILE_DETAIL_DATA_URL = `${BASE_URL}/compare-compile-detail-graphs`;
10+
export const COMPARE_COMPILE_DETAIL_GRAPHS_DATA_URL = `${BASE_URL}/compare-compile-detail-graphs`;
1111
export const SELF_PROFILE_DATA_URL = `${BASE_URL}/self-profile`;

0 commit comments

Comments
 (0)