summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAnna Henningsen <anna@addaleax.net>2018-07-01 01:27:09 +0200
committerAnna Henningsen <anna@addaleax.net>2018-07-15 20:35:41 +0200
commit45ad8df318390b54ea6cb54b4b4b320875f9c88f (patch)
treedf48dc0d6595cf726fe604a1133284ad79aad931 /lib
parent266a7e62585b975f2ea2d25473b21395f5ca5a3f (diff)
downloadandroid-node-v8-45ad8df318390b54ea6cb54b4b4b320875f9c88f.tar.gz
android-node-v8-45ad8df318390b54ea6cb54b4b4b320875f9c88f.tar.bz2
android-node-v8-45ad8df318390b54ea6cb54b4b4b320875f9c88f.zip
src: make heap snapshot & embedder graph accessible for tests
Add methods that allow inspection of heap snapshots and a JS version of our own embedder graph. These can be used in tests and might also prove useful for ad-hoc debugging. Usage requires `--expose-internals` and prints a warning similar to our other modules whose primary purpose is test support. PR-URL: https://github.com/nodejs/node/pull/21741 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: Refael Ackermann <refack@gmail.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/internal/test/heap.js87
1 files changed, 87 insertions, 0 deletions
diff --git a/lib/internal/test/heap.js b/lib/internal/test/heap.js
new file mode 100644
index 0000000000..a9260f651b
--- /dev/null
+++ b/lib/internal/test/heap.js
@@ -0,0 +1,87 @@
+'use strict';
+
+process.emitWarning(
+ 'These APIs are exposed only for testing and are not ' +
+ 'tracked by any versioning system or deprecation process.',
+ 'internal/test/heap');
+
+const { internalBinding } = require('internal/bootstrap/loaders');
+const { createHeapDump, buildEmbedderGraph } = internalBinding('heap_utils');
+const assert = require('assert');
+
+// This is not suitable for production code. It creates a full V8 heap dump,
+// parses it as JSON, and then creates complex objects from it, leading
+// to significantly increased memory usage.
+function createJSHeapDump() {
+ const dump = createHeapDump();
+ const meta = dump.snapshot.meta;
+
+ const nodes =
+ readHeapInfo(dump.nodes, meta.node_fields, meta.node_types, dump.strings);
+ const edges =
+ readHeapInfo(dump.edges, meta.edge_fields, meta.edge_types, dump.strings);
+
+ for (const node of nodes) {
+ node.incomingEdges = [];
+ node.outgoingEdges = [];
+ }
+
+ let fromNodeIndex = 0;
+ let edgeIndex = 0;
+ for (const { type, name_or_index, to_node } of edges) {
+ while (edgeIndex === nodes[fromNodeIndex].edge_count) {
+ edgeIndex = 0;
+ fromNodeIndex++;
+ }
+ const toNode = nodes[to_node / meta.node_fields.length];
+ const fromNode = nodes[fromNodeIndex];
+ const edge = {
+ type,
+ toNode,
+ fromNode,
+ name: typeof name_or_index === 'string' ? name_or_index : null
+ };
+ toNode.incomingEdges.push(edge);
+ fromNode.outgoingEdges.push(edge);
+ edgeIndex++;
+ }
+
+ for (const node of nodes)
+ assert.strictEqual(node.edge_count, node.outgoingEdges.length);
+
+ return nodes;
+}
+
+function readHeapInfo(raw, fields, types, strings) {
+ const items = [];
+
+ for (var i = 0; i < raw.length; i += fields.length) {
+ const item = {};
+ for (var j = 0; j < fields.length; j++) {
+ const name = fields[j];
+ let type = types[j];
+ if (Array.isArray(type)) {
+ item[name] = type[raw[i + j]];
+ } else if (name === 'name_or_index') { // type === 'string_or_number'
+ if (item.type === 'element' || item.type === 'hidden')
+ type = 'number';
+ else
+ type = 'string';
+ }
+
+ if (type === 'string') {
+ item[name] = strings[raw[i + j]];
+ } else if (type === 'number' || type === 'node') {
+ item[name] = raw[i + j];
+ }
+ }
+ items.push(item);
+ }
+
+ return items;
+}
+
+module.exports = {
+ createJSHeapDump,
+ buildEmbedderGraph
+};