Skip to content

Commit 4f41328

Browse files
committed
new utility: report-profile.ts
1 parent 6173a70 commit 4f41328

File tree

3 files changed

+132
-0
lines changed

3 files changed

+132
-0
lines changed
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import { LuaStack } from "./types.ts";
2+
3+
export const loadProfilerData = (filename: string, frameSkip: number = 3): LuaStack[] => {
4+
let longestCommonPrefix: string | undefined = undefined;
5+
const file = Deno.readTextFileSync(filename);
6+
// find the longest common prefix for source to trim
7+
for (const fileLine of file.split("\n")) {
8+
if (fileLine === "")
9+
continue;
10+
const entries = fileLine.split(" ");
11+
if (entries.length === 4) {
12+
continue;
13+
}
14+
const [_name, source] = fileLine.split(" ");
15+
if (source === "=[C]") continue;
16+
17+
if (longestCommonPrefix === undefined) {
18+
longestCommonPrefix = source;
19+
} else {
20+
// find the longest common prefix
21+
let i = 0;
22+
while (i < longestCommonPrefix.length && longestCommonPrefix[i] === source[i]) {
23+
i++;
24+
}
25+
longestCommonPrefix = longestCommonPrefix.slice(0, i);
26+
}
27+
}
28+
29+
if (longestCommonPrefix === undefined) {
30+
throw new Error("Internal error: no common prefix found");
31+
}
32+
33+
type LuaStack = {
34+
frames: LuaStackFrame[];
35+
time: number;
36+
line: number;
37+
category: string;
38+
}
39+
40+
type LuaStackFrame = {
41+
location: string;
42+
// name: string;
43+
// source: string;
44+
// line: number;
45+
}
46+
47+
const stacks: LuaStack[] = [];
48+
let stackNum = "";
49+
let time = 0;
50+
let thisStack: LuaStackFrame[] = [];
51+
let category = "";
52+
53+
for (const fileLine of file.split("\n")) {
54+
if (fileLine === "") continue;
55+
const entries = fileLine.split(" ");
56+
if (entries.length === 4) {
57+
category = entries[2];
58+
if (stackNum !== entries[0]) {
59+
if (thisStack.length) {
60+
thisStack[0].location = `${thisStack[0].location}:${entries[3]}`;
61+
}
62+
stacks.push({
63+
frames: thisStack,
64+
time: Number(entries[1]),
65+
line: Number(entries[3]),
66+
category
67+
});
68+
thisStack = [];
69+
stackNum = entries[0];
70+
}
71+
continue;
72+
}
73+
const [name, source, line] = fileLine.split(" ");
74+
try {
75+
const frame: LuaStackFrame = {
76+
location: `${source.slice(longestCommonPrefix.length)}:${line}:${name}`,
77+
};
78+
thisStack.push(frame);
79+
} catch (_e) {
80+
throw new Error(`Error parsing line: ${fileLine}`);
81+
}
82+
}
83+
84+
return stacks;
85+
}

tools/profiler/report-profile.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { loadProfilerData } from "./lua-profiler-data-loader.ts";
2+
import { LuaStack } from "./types.ts";
3+
4+
const filename = Deno.args[0];
5+
const frameSkip = Deno.args[1] === undefined ? 3 : Number(Deno.args[1]);
6+
const stacks = loadProfilerData(filename, frameSkip);
7+
8+
const estimateSampleRate = (stacks: LuaStack[]) => {
9+
return (stacks[stacks.length - 1].time - stacks[0].time) / (stacks.length - 1);
10+
}
11+
12+
const totalTime = stacks[stacks.length - 1].time - stacks[0].time;
13+
const sampleRate = estimateSampleRate(stacks);
14+
15+
const selfTimes = new Map<string, number>();
16+
17+
for (const stack of stacks) {
18+
const topFrame = stack.frames[0];
19+
const location = topFrame.location;
20+
if (!selfTimes.has(location)) {
21+
selfTimes.set(location, 0);
22+
}
23+
selfTimes.set(location, selfTimes.get(location)! + sampleRate);
24+
}
25+
26+
const roundToDigits = (num: number, digits: number) => {
27+
const factor = 10 ** digits;
28+
return Math.round(num * factor) / factor;
29+
}
30+
31+
console.log(
32+
Array.from(selfTimes.entries())
33+
.sort((a, b) => b[1] - a[1])
34+
.map(([location, time]) => `${roundToDigits(100 * time / totalTime, 1)}% (${roundToDigits(time, 3)}): ${location}`).join("\n"));

tools/profiler/types.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
export type LuaStack = {
2+
frames: LuaStackFrame[];
3+
time: number;
4+
line: number;
5+
category: string;
6+
}
7+
8+
export type LuaStackFrame = {
9+
location: string;
10+
// name: string;
11+
// source: string;
12+
// line: number;
13+
}

0 commit comments

Comments
 (0)