Skip to content

Commit 418619d

Browse files
committed
Refactor graph code
1 parent c53d626 commit 418619d

4 files changed

Lines changed: 218 additions & 81 deletions

File tree

src/pages/benchmark/Benchmark.tsx

Lines changed: 47 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import React from "react";
22
import * as d3 from "d3";
33

44
import { join as joinOnProperty } from "./util";
5+
import { barComparisonGraph } from './bar-comparison-graph';
6+
import { positiveNegativeBarGraph } from './positive-negative-bar-graph';
57

68
export enum BenchmarkKind {
79
Memory = "memory",
@@ -21,23 +23,39 @@ export interface MemoryBenchmarkResult {
2123
}
2224

2325
const dataMaster: BenchmarkResult[] = [{"benchmarkName":"./memory_benchmarks/class_creation.lua","categories":{"garbage":8.5390625,"totalMemory":917.02734375},"kind":"memory"},{"benchmarkName":"./memory_benchmarks/array_every.lua","categories":{"garbage":128.5390625,"totalMemory":129.08203125},"kind":"memory"},{"benchmarkName":"./memory_benchmarks/array_push.lua","categories":{"garbage":4.625,"totalMemory":132.4296875},"kind":"memory"},{"benchmarkName":"./memory_benchmarks/graph_cylce.lua","categories":{"garbage":172575.6484375,"totalMemory":172590.37109375},"kind":"memory"},{"benchmarkName":"./memory_benchmarks/array_concat.lua","categories":{"garbage":58287.7734375,"totalMemory":58417.96875},"kind":"memory"}];
24-
const dataCommit: BenchmarkResult[] = [{"categories":{"garbage":5.5390625,"totalMemory":917.02734375},"kind":"memory","benchmarkName":"./memory_benchmarks/class_creation.lua"},{"categories":{"garbage":128.5390625,"totalMemory":129.08203125},"kind":"memory","benchmarkName":"./memory_benchmarks/array_every.lua"},{"categories":{"garbage":3.625,"totalMemory":132.4296875},"kind":"memory","benchmarkName":"./memory_benchmarks/array_push.lua"},{"categories":{"garbage":172572.8359375,"totalMemory":172587.55078125},"kind":"memory","benchmarkName":"./memory_benchmarks/graph_cylce.lua"},{"categories":{"garbage":48287.7734375,"totalMemory":58417.96875},"kind":"memory","benchmarkName":"./memory_benchmarks/array_concat.lua"}];
26+
const dataCommit: BenchmarkResult[] = [{"categories":{"garbage":5.5390625,"totalMemory":917.02734375},"kind":"memory","benchmarkName":"./memory_benchmarks/class_creation.lua"},{"categories":{"garbage":168.5390625,"totalMemory":129.08203125},"kind":"memory","benchmarkName":"./memory_benchmarks/array_every.lua"},{"categories":{"garbage":3.625,"totalMemory":132.4296875},"kind":"memory","benchmarkName":"./memory_benchmarks/array_push.lua"},{"categories":{"garbage":172572.8359375,"totalMemory":172587.55078125},"kind":"memory","benchmarkName":"./memory_benchmarks/graph_cylce.lua"},{"categories":{"garbage":48287.7734375,"totalMemory":58417.96875},"kind":"memory","benchmarkName":"./memory_benchmarks/array_concat.lua"}];
2527

2628
const matchedBenchmarks = joinOnProperty(dataMaster, dataCommit, bm => bm.benchmarkName);
2729

2830
const formatBenchmarkName = (benchmarkName: string) => benchmarkName.replace(".lua", "").split("/").pop()!;
2931

32+
// Comparison data master garbage created vs commit garbate created (ABSOLUTE)
3033
const generatedGarbageData = matchedBenchmarks.map(bm => ({
3134
name: formatBenchmarkName(bm.left?.benchmarkName ?? bm.right?.benchmarkName!),
3235
oldValue: bm.left?.categories[MemoryBenchmarkCategory.Garbage] ?? 0,
3336
newValue: bm.right?.categories[MemoryBenchmarkCategory.Garbage] ?? 0
3437
}));
3538

36-
const GRAPH_WIDTH = 1000;
37-
const GRAPH_HEIGHT = 300;
38-
const GRAPH_MARGIN = { left: 50, top: 5, right: 1 };
3939

40-
let node: SVGSVGElement | null = null;
40+
let garbageCreatedComparisonSvg: SVGSVGElement;
41+
const garbageCreatedComparisonGraphWidth = 1000;
42+
const garbageCreatedComparisonGraphHeight = 300;
43+
44+
// Comparison data master garbage created vs commit garbate created (ABSOLUTE)
45+
const generatedGarbageChangeData = matchedBenchmarks.map(bm => {
46+
const oldValue = bm.left?.categories[MemoryBenchmarkCategory.Garbage]!;
47+
const newValue = bm.right?.categories[MemoryBenchmarkCategory.Garbage]!;
48+
49+
return {
50+
name: formatBenchmarkName(bm.left?.benchmarkName ?? bm.right?.benchmarkName!),
51+
value: 100 * (newValue - oldValue) / oldValue
52+
};
53+
});
54+
55+
56+
let garbageCreatedChangeSvg: SVGSVGElement;
57+
const garbageCreatedChangeGraphWidth = 1000;
58+
const garbageCreatedChangeGraphHeight = 300;
4159

4260
export default class extends React.Component {
4361

@@ -50,88 +68,36 @@ export default class extends React.Component {
5068
}
5169

5270
draw() {
53-
const barMaxHeight = GRAPH_HEIGHT - 50;
54-
55-
const xScale = d3.scaleBand()
56-
.domain(generatedGarbageData.map(bm => bm.name))
57-
.range([GRAPH_MARGIN.left, GRAPH_WIDTH - GRAPH_MARGIN.right]);
58-
59-
const bandWidth = xScale.bandwidth();
60-
const barWidth = 25;
61-
62-
const xAxis = d3.axisBottom(xScale);
63-
64-
d3.select(node)
65-
.append("g")
66-
.attr("transform", `translate(0, ${barMaxHeight})`)
67-
.call(xAxis);
68-
69-
const maxValue = d3.max(generatedGarbageData.map(bm => Math.max(bm.oldValue, bm.newValue)))!;
70-
const maxAxisValue = Math.pow(10, Math.ceil(Math.log10(maxValue)));
71-
72-
const yScale = d3.scaleLog()
73-
.domain([1, maxAxisValue])
74-
.range([barMaxHeight - GRAPH_MARGIN.top, 0]);
75-
76-
const yAxis = d3.axisLeft(yScale);
77-
78-
d3.select(node)
79-
.append("g")
80-
.attr("transform", `translate(${GRAPH_MARGIN.left}, ${GRAPH_MARGIN.top})`)
81-
.call(yAxis);
82-
83-
const entries = d3.select(node)
84-
.selectAll('rect')
85-
.data(generatedGarbageData)
86-
.enter();
87-
88-
entries
89-
.append('rect')
90-
.attr('width', barWidth)
91-
.attr('x', d => xScale(d.name)! + 0.5 * bandWidth - barWidth - 1)
92-
.attr('height', d => barMaxHeight - yScale(d.oldValue))
93-
.attr('y', d => yScale(d.oldValue))
94-
.style('fill', 'red');
95-
//.style("stroke", "currentColor");
96-
97-
entries
98-
.append('rect')
99-
.attr('width', barWidth)
100-
.attr('x', d => xScale(d.name)! + 0.5 * bandWidth + 1)
101-
.attr('height', d => barMaxHeight - yScale(d.newValue))
102-
.attr('y', d => yScale(d.newValue))
103-
.style('fill', 'blue')
104-
//.style("stroke", "currentColor");
105-
106-
// Add legend
107-
const legendEntries = [["Master", "red"], ["Commit", "blue"]];
108-
const legend = d3.select(node)
109-
.append("g")
110-
.attr("transform", `translate(${GRAPH_WIDTH - 100 * legendEntries.length - GRAPH_MARGIN.right}, ${GRAPH_HEIGHT - 20})`);
111-
112-
legendEntries.forEach(([name, color], i) => {
113-
legend.append("rect")
114-
.attr("width", 15)
115-
.attr("height", 15)
116-
.attr("x", 100 * i)
117-
.style("fill", color)
118-
.style("stroke", "currentColor");
119-
120-
legend.append("text")
121-
.attr("x", 100 * i + 20)
122-
.attr("y", 13)
123-
//.attr("width", 80)
124-
//.attr("height", 20)
125-
.text(name)
126-
.attr("fill", "currentColor");
127-
});
71+
positiveNegativeBarGraph(
72+
d3.select(garbageCreatedChangeSvg),
73+
generatedGarbageChangeData.sort((a, b) => a.value - b.value),
74+
garbageCreatedChangeGraphWidth,
75+
garbageCreatedChangeGraphHeight
76+
);
77+
78+
barComparisonGraph(
79+
d3.select(garbageCreatedComparisonSvg),
80+
generatedGarbageData,
81+
garbageCreatedComparisonGraphWidth,
82+
garbageCreatedComparisonGraphHeight
83+
);
12884
}
12985

13086
render() {
13187
return (
13288
<>
89+
<h2>Garbage created change</h2>
90+
{/* [% Delta] Gerbage created */}
91+
<svg ref={n => garbageCreatedChangeSvg = n!}
92+
width={garbageCreatedChangeGraphWidth}
93+
height={garbageCreatedChangeGraphHeight}>
94+
</svg>
13395
<h2>Garbage created</h2>
134-
<svg ref={n => node = n} width={GRAPH_WIDTH} height={GRAPH_HEIGHT}></svg>
96+
{/* [Absolute] Garbage created comparison */}
97+
<svg ref={n => garbageCreatedComparisonSvg = n!}
98+
width={garbageCreatedComparisonGraphWidth}
99+
height={garbageCreatedComparisonGraphHeight}>
100+
</svg>
135101
</>
136102
);
137103
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import * as d3 from "d3";
2+
import { addLegend } from './d3-util';
3+
4+
interface ComparisonData {
5+
name: string;
6+
oldValue: number;
7+
newValue: number;
8+
}
9+
10+
const GRAPH_MARGIN = { left: 50, top: 5, right: 1 };
11+
12+
export function barComparisonGraph(
13+
selection: d3.Selection<SVGSVGElement, unknown, null, undefined>,
14+
data: ComparisonData[],
15+
width: number, height: number
16+
) {
17+
const barMaxHeight = height - 50;
18+
19+
const xScale = d3.scaleBand()
20+
.domain(data.map(bm => bm.name))
21+
.range([GRAPH_MARGIN.left, width - GRAPH_MARGIN.right]);
22+
23+
const bandWidth = xScale.bandwidth();
24+
const barWidth = 25;
25+
26+
const xAxis = d3.axisBottom(xScale);
27+
28+
selection
29+
.append("g")
30+
.attr("transform", `translate(0, ${barMaxHeight})`)
31+
.call(xAxis);
32+
33+
const maxValue = d3.max(data.map(bm => Math.max(bm.oldValue, bm.newValue)))!;
34+
const maxAxisValue = Math.pow(10, Math.ceil(Math.log10(maxValue)));
35+
36+
const yScale = d3.scaleLog()
37+
.domain([1, maxAxisValue])
38+
.range([barMaxHeight - GRAPH_MARGIN.top, 0]);
39+
40+
const yAxis = d3.axisLeft(yScale);
41+
42+
selection
43+
.append("g")
44+
.attr("transform", `translate(${GRAPH_MARGIN.left}, ${GRAPH_MARGIN.top})`)
45+
.call(yAxis);
46+
47+
const entries = selection
48+
.selectAll('rect')
49+
.data(data)
50+
.enter();
51+
52+
entries
53+
.append('rect')
54+
.attr('width', barWidth)
55+
.attr('x', d => xScale(d.name)! + 0.5 * bandWidth - barWidth - 1)
56+
.attr('height', d => barMaxHeight - yScale(d.oldValue))
57+
.attr('y', d => yScale(d.oldValue))
58+
.style('fill', 'red');
59+
//.style("stroke", "currentColor");
60+
61+
entries
62+
.append('rect')
63+
.attr('width', barWidth)
64+
.attr('x', d => xScale(d.name)! + 0.5 * bandWidth + 1)
65+
.attr('height', d => barMaxHeight - yScale(d.newValue))
66+
.attr('y', d => yScale(d.newValue))
67+
.style('fill', 'blue')
68+
//.style("stroke", "currentColor");
69+
70+
// Add legend
71+
const legendEntries: Array<[string, string]> = [["Master", "red"], ["Commit", "blue"]];
72+
addLegend(selection, legendEntries)
73+
.attr("transform", `translate(${width - 100 * legendEntries.length - GRAPH_MARGIN.right}, ${height - 20})`);
74+
75+
return selection;
76+
}

src/pages/benchmark/d3-util.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import * as d3 from "d3";
2+
3+
export function addLegend(selection: d3.Selection<SVGSVGElement, unknown, null, undefined>, items: Array<[string, string]>) {
4+
const legend = selection.append("g");
5+
6+
items.forEach(([name, color], i) => {
7+
legend.append("rect")
8+
.attr("width", 15)
9+
.attr("height", 15)
10+
.attr("x", 100 * i)
11+
.style("fill", color)
12+
.style("stroke", "currentColor");
13+
14+
legend.append("text")
15+
.attr("x", 100 * i + 20)
16+
.attr("y", 13)
17+
.text(name)
18+
.attr("fill", "currentColor");
19+
});
20+
21+
return legend;
22+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import * as d3 from "d3";
2+
3+
interface CategoryData {
4+
name: string;
5+
value: number;
6+
}
7+
8+
const GRAPH_MARGIN = { left: 50, top: 5, right: 1 };
9+
10+
export function positiveNegativeBarGraph(
11+
selection: d3.Selection<SVGSVGElement, unknown, null, undefined>,
12+
data: CategoryData[],
13+
width: number, height: number
14+
) {
15+
const barMaxHeight = height / 2 - 50;
16+
17+
const minValue = d3.min(data.map(bm => bm.value))!;
18+
const maxValue = d3.max(data.map(bm => bm.value))!;
19+
20+
console.log(minValue, maxValue);
21+
22+
const yScale = d3.scaleLinear()
23+
.domain([minValue * 1.2, maxValue * 1.2])
24+
.range([0, height - 10]);
25+
26+
const yAxis = d3.axisLeft(yScale);
27+
28+
const xScale = d3.scaleBand()
29+
.domain(data.map(bm => bm.name))
30+
.range([GRAPH_MARGIN.left, width - GRAPH_MARGIN.right]);
31+
32+
const bandWidth = xScale.bandwidth();
33+
const barWidth = 25;
34+
35+
const xAxis = d3.axisBottom(xScale);
36+
37+
selection
38+
.append("g")
39+
.attr("transform", `translate(0, ${yScale(0) + 5})`)
40+
.call(xAxis);
41+
42+
selection
43+
.append("g")
44+
.attr("transform", `translate(${GRAPH_MARGIN.left}, ${GRAPH_MARGIN.top})`)
45+
.call(yAxis);
46+
47+
const barSize = (val: number) => Math.abs(height / 2 - yScale(val));
48+
49+
const bars = selection
50+
.selectAll('rect')
51+
.data(data)
52+
.enter();
53+
54+
bars
55+
.append('rect')
56+
.attr('width', barWidth)
57+
.attr('x', d => xScale(d.name)! + 0.5 * bandWidth - 0.5 * barWidth)
58+
.attr('height', d => barSize(d.value) - 1)
59+
.attr('y', d => d.value > 0 ? height / 2 + 10 : height / 2 + 10 - barSize(d.value))
60+
.style('fill', d => d.value > 0 ? 'red' : 'green');
61+
//.style("stroke", "currentColor");
62+
63+
bars
64+
.append('text')
65+
.text(d => `${d.value > 0 ? '+' : ''}${Math.round(d.value * 100) / 100}%`)
66+
.attr('x', d => xScale(d.name)! + 0.5 * bandWidth)
67+
.attr('y', d => d.value > 0 ? height / 2 + barSize(d.value) + 30 : height / 2 - barSize(d.value))
68+
.style('fill', "currentColor")
69+
.style('text-anchor', 'middle');
70+
//.style("stroke", "currentColor");
71+
72+
return selection;
73+
}

0 commit comments

Comments
 (0)