-
-
Notifications
You must be signed in to change notification settings - Fork 18
Expand file tree
/
Copy pathmemory-spike.js
More file actions
109 lines (95 loc) · 2.43 KB
/
memory-spike.js
File metadata and controls
109 lines (95 loc) · 2.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
const v8 = require("node:v8");
const translateHeapStats = (stats = []) => {
const result = {};
for (const { space_name, space_used_size } of stats) {
result[space_name] = space_used_size;
}
return result;
};
const updateMaxEachKey = (current, update) => {
for (const key in current) {
current[key] = Math.max(current[key], update[key]);
}
};
const diffEachKey = (a, b, divBy = 1) => {
const result = {};
for (const key in a) {
result[key] = (b[key] - a[key]) / divBy;
}
return result;
};
const avgEachKey = (items) => {
const result = {};
for (const item of items) {
for (const key in item) {
result[key] = (result[key] || 0) + item[key];
}
}
for (const key in result) {
result[key] /= items.length;
}
return result;
};
const toHumanReadable = (obj) => {
const result = {};
for (const key in obj) {
if (obj[key] > 0) result[key] = `+${(obj[key] / 1024).toFixed(4)} KB`;
}
return result;
};
globalThis.__recordMemorySpike = (frequency = 2) => {
const initial = translateHeapStats(v8.getHeapSpaceStatistics());
const result = { ...initial };
const collect = () =>
updateMaxEachKey(result, translateHeapStats(v8.getHeapSpaceStatistics()));
const interval = setInterval(collect, frequency);
return {
collect,
getResult: () => {
clearInterval(interval);
collect();
return [initial, result];
},
};
};
class RecordMemorySpikePlugin {
#spikeSamples = {};
isSupported() {
try {
new Function(`gc()`)();
return true;
} catch (e) {
return false;
}
}
beforeClockTemplate() {
return [`const __mem_spike__ = __recordMemorySpike();`];
}
afterClockTemplate({ context, bench }) {
return [
`;
${context}.benchName=${bench}.name;
${context}.memSpike = __mem_spike__.getResult();
`,
];
}
onCompleteBenchmark([_time, iterations, results]) {
gc();
const [initial, result] = results.memSpike;
const diff = diffEachKey(initial, result, iterations);
if (!this.#spikeSamples[results.benchName]) {
this.#spikeSamples[results.benchName] = [];
}
this.#spikeSamples[results.benchName].push(diff);
}
getResult(name) {
return toHumanReadable(avgEachKey(this.#spikeSamples[name]));
}
getReport() {
process._rawDebug('grp',arguments);
}
toString() {
return "RecordMemorySpikePlugin";
}
}
exports.RecordMemorySpikePlugin = RecordMemorySpikePlugin;