reorganize data; show flamegraph

This commit is contained in:
Theis Pieter Hollebeek 2024-12-06 13:17:07 +01:00
parent fd072ce0e9
commit aa888c9368
3 changed files with 79 additions and 49 deletions

View File

@ -1,7 +1,6 @@
{
"tasks": {
"bundle": "deno run -A bundle.ts",
"dev": "deno run --watch -A bundle.ts"
"bundle": "deno run -A bundle.ts"
},
"compilerOptions": {
"checkJs": false,

43
web/public/src/data.ts Normal file
View File

@ -0,0 +1,43 @@
export type FlameGraphNode = {
fn: number;
acc: number;
parent: number;
children: FlameGraphNode[];
};
export function flameGraphData(): FlameGraphNode {
return JSON.parse(
`{"fn":0,"acc":257,"parent":0,"children":[{"fn":18,"acc":251,"parent":0,"children":[{"fn":12,"acc":30,"parent":1,"children":[]}]}]}`,
);
}
export function codeData() {
return `\
fn add(a, b) {
+ a b
}
let result = 0;
let i = 0;
loop {
if >= i 10 {
break;
}
result = add(result, 5);
i = + i 1;
}
`;
}
export type CodeCovEntry = {
index: number;
line: number;
col: number;
covers: number;
};
export function codeCoverageData(): CodeCovEntry[] {
return JSON.parse(
`[{"index":0,"line":1,"col":1,"covers":2},{"index":28,"line":5,"col":1,"covers":1},{"index":44,"line":6,"col":1,"covers":1},{"index":55,"line":7,"col":1,"covers":1},{"index":66,"line":8,"col":5,"covers":11},{"index":104,"line":11,"col":5,"covers":10},{"index":19,"line":2,"col":5,"covers":10},{"index":133,"line":12,"col":5,"covers":10},{"index":87,"line":9,"col":9,"covers":1}]`,
);
}

View File

@ -1,9 +1,10 @@
type CodeCovEntry = {
index: number;
line: number;
col: number;
covers: number;
};
import {
CodeCovEntry,
codeCoverageData,
codeData,
flameGraphData,
FlameGraphNode,
} from "./data.ts";
function loadCodeCoverage(
text: string,
@ -93,8 +94,13 @@ function loadCodeCoverage(
});
}
// @ts-ignore: unsure of relevant types
function loadFlameGraph(flameGraphData, fnNames, flameGraphDiv) {
type FlameGraphFnNames = { [key: number]: string };
function loadFlameGraph(
flameGraphData: FlameGraphNode,
fnNames: FlameGraphFnNames,
flameGraphDiv: HTMLDivElement,
) {
flameGraphDiv.innerHTML = `
<canvas id="flame-graph-canvas"></canvas>
<span id="flame-graph-tooltip" hidden></span>
@ -120,8 +126,12 @@ function loadFlameGraph(flameGraphData, fnNames, flameGraphDiv) {
const nodes: Node[] = [];
// @ts-ignore: unsure of relevant types
function calculateNodeRects(node, depth, totalAcc, offsetAcc) {
function calculateNodeRects(
node: FlameGraphNode,
depth: number,
totalAcc: FlameGraphNode["acc"],
offsetAcc: FlameGraphNode["acc"],
) {
const x = (offsetAcc / totalAcc) * canvas.width;
const y = canvas.height - 30 * depth - 30;
const w = ((node.acc + 1) / totalAcc) * canvas.width;
@ -132,7 +142,6 @@ function loadFlameGraph(flameGraphData, fnNames, flameGraphDiv) {
nodes.push({ x, y, w, h, title, percent });
const totalChildrenAcc = node.children.reduce(
// @ts-ignore: unsure of relevant types
(acc, child) => acc + child.acc,
0,
);
@ -186,30 +195,6 @@ function loadFlameGraph(flameGraphData, fnNames, flameGraphDiv) {
}
function main() {
const codeData = `\
fn add(a, b) {
+ a b
}
let result = 0;
let i = 0;
loop {
if >= i 10 {
break;
}
result = add(result, 5);
i = + i 1;
}
`;
const codeCoverageData = JSON.parse(
`[{"index":0,"line":1,"col":1,"covers":2},{"index":28,"line":5,"col":1,"covers":1},{"index":44,"line":6,"col":1,"covers":1},{"index":55,"line":7,"col":1,"covers":1},{"index":66,"line":8,"col":5,"covers":11},{"index":104,"line":11,"col":5,"covers":10},{"index":19,"line":2,"col":5,"covers":10},{"index":133,"line":12,"col":5,"covers":10},{"index":87,"line":9,"col":9,"covers":1}]`,
);
const flameGraphData = JSON.parse(
`{"fn":0,"acc":257,"parent":0,"children":[{"fn":18,"acc":251,"parent":0,"children":[{"fn":12,"acc":30,"parent":1,"children":[]}]}]}`,
);
type RenderFns = {
"source-code": () => void;
"code-coverage": () => void;
@ -244,9 +229,9 @@ loop {
"source-code": () => {
const container = document.createElement("div");
container.classList.add("code-container");
const lines = createLineElement(codeData);
const lines = createLineElement(codeData());
const code = document.createElement("pre");
code.innerText = codeData;
code.innerText = codeData();
container.append(lines, code);
view.replaceChildren(container);
},
@ -255,14 +240,24 @@ loop {
container.classList.add("code-container");
const tooltip = document.createElement("div");
tooltip.id = "covers-tooltip";
tooltip.hidden = true;
const code = document.createElement("pre");
loadCodeCoverage(codeData, codeCoverageData, code, tooltip);
const lines = createLineElement(codeData);
loadCodeCoverage(codeData(), codeCoverageData(), code, tooltip);
const lines = createLineElement(codeData());
container.append(lines, code);
const view = document.querySelector("#view")!;
view.replaceChildren(container, tooltip);
},
"flame-graph": () => {},
"flame-graph": () => {
const container = document.createElement("div");
const view = document.querySelector("#view")!;
view.replaceChildren(container);
loadFlameGraph(flameGraphData(), {
0: "<entry>",
12: "add",
18: "main",
}, container);
},
};
const viewRadios: NodeListOf<HTMLInputElement> = document.querySelectorAll(
@ -279,13 +274,6 @@ loop {
renderFunctions[value]();
}
}
// loadCodeCoverage(codeData, codeCoverageData);
// loadFlameGraph(flameGraphData, {
// 0: "<entry>",
// 12: "add",
// 18: "main",
// });
}
main();