Skip to content

Commit 30b4ca6

Browse files
committed
src: expose size and count in heap profile output
1 parent 5ed55ba commit 30b4ca6

3 files changed

Lines changed: 43 additions & 1 deletion

File tree

doc/api/v8.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1628,6 +1628,16 @@ added: v26.1.0
16281628
16291629
Stopping collecting the profile and return the profile data.
16301630
1631+
The returned string is JSON in the Chrome DevTools sampling heap profile
1632+
format, with a `head` call-tree and a `samples` array. On top of the DevTools
1633+
fields, the following are added:
1634+
1635+
* Each node reports `selfCount`, the number of sampled objects allocated by the
1636+
node (`selfSize` is the existing total in bytes).
1637+
* Each sample reports `objectSize`, `objectCount`, and `isLive`.
1638+
1639+
The DevTools `size` field stays `objectSize * objectCount` for compatibility.
1640+
16311641
### `syncHeapProfileHandle[Symbol.dispose]()`
16321642
16331643
<!-- YAML

src/node_profiling.cc

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,14 @@ static void BuildHeapProfileNode(Isolate* isolate,
1717
const AllocationProfile::Node* node,
1818
JSONWriter* writer) {
1919
size_t selfSize = 0;
20-
for (const auto& allocation : node->allocations)
20+
size_t selfCount = 0;
21+
for (const auto& allocation : node->allocations) {
2122
selfSize += allocation.size * allocation.count;
23+
selfCount += allocation.count;
24+
}
2225

2326
writer->json_keyvalue("selfSize", selfSize);
27+
writer->json_keyvalue("selfCount", selfCount);
2428
writer->json_keyvalue("id", node->node_id);
2529
writer->json_objectstart("callFrame");
2630
writer->json_keyvalue("scriptId", node->script_id);
@@ -55,8 +59,11 @@ bool SerializeHeapProfile(Isolate* isolate, std::ostringstream& out_stream) {
5559
for (const auto& sample : profile->GetSamples()) {
5660
writer.json_start();
5761
writer.json_keyvalue("size", sample.size * sample.count);
62+
writer.json_keyvalue("objectSize", sample.size);
63+
writer.json_keyvalue("objectCount", sample.count);
5864
writer.json_keyvalue("nodeId", sample.node_id);
5965
writer.json_keyvalue("ordinal", static_cast<double>(sample.sample_id));
66+
writer.json_keyvalue("isLive", sample.is_live);
6067
writer.json_end();
6168
}
6269
writer.json_arrayend();

test/parallel/test-v8-heap-profile.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,31 @@ for (const value of invalidLimits) {
7373
JSON.parse(profile);
7474
}
7575

76+
{
77+
const handle = v8.startHeapProfile({ sampleInterval: 1, stackDepth: 8 });
78+
const retained = [];
79+
for (let i = 0; i < 4096; i++) {
80+
retained.push({ i, payload: new Array(16).fill(i) });
81+
}
82+
const parsed = JSON.parse(handle.stop());
83+
84+
assert.strictEqual(typeof parsed.head.selfSize, 'number');
85+
assert.strictEqual(typeof parsed.head.selfCount, 'number');
86+
assert.strictEqual(typeof parsed.head.id, 'number');
87+
assert.strictEqual(typeof parsed.head.callFrame, 'object');
88+
89+
assert(parsed.samples.length > 0);
90+
for (const sample of parsed.samples) {
91+
assert.strictEqual(typeof sample.size, 'number');
92+
assert.strictEqual(typeof sample.objectSize, 'number');
93+
assert.strictEqual(typeof sample.objectCount, 'number');
94+
assert.strictEqual(typeof sample.nodeId, 'number');
95+
assert.strictEqual(typeof sample.ordinal, 'number');
96+
assert.strictEqual(typeof sample.isLive, 'boolean');
97+
assert.strictEqual(sample.size, sample.objectSize * sample.objectCount);
98+
}
99+
}
100+
76101
// Second stop returns undefined.
77102
{
78103
const handle = v8.startHeapProfile();

0 commit comments

Comments
 (0)