@memlab/heap-analysis 1.0.5 → 1.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/BaseAnalysis.d.ts +1 -1
- package/dist/BaseAnalysis.js +2 -2
- package/dist/HeapAnalysisLoader.d.ts +1 -1
- package/dist/HeapAnalysisLoader.js +1 -1
- package/dist/HeapConfig.d.ts +21 -0
- package/dist/HeapConfig.js +29 -0
- package/dist/PluginUtils.d.ts +31 -5
- package/dist/PluginUtils.js +85 -10
- package/dist/__tests__/HeapAnalysis.test.d.ts +1 -1
- package/dist/__tests__/HeapAnalysis.test.js +20 -2
- package/dist/__tests__/package.test.js +8 -7
- package/dist/index.d.ts +6 -2
- package/dist/index.js +8 -3
- package/dist/options/HeapAnalysisNodeIdOption.d.ts +19 -0
- package/dist/options/HeapAnalysisNodeIdOption.js +45 -0
- package/dist/options/HeapAnalysisSnapshotDirectoryOption.d.ts +1 -1
- package/dist/options/HeapAnalysisSnapshotDirectoryOption.js +1 -1
- package/dist/options/HeapAnalysisSnapshotFileOption.d.ts +1 -1
- package/dist/options/HeapAnalysisSnapshotFileOption.js +1 -1
- package/dist/plugins/CollectionsHoldingStaleAnalysis.d.ts +1 -1
- package/dist/plugins/CollectionsHoldingStaleAnalysis.js +1 -1
- package/dist/plugins/DetachedDOMElementAnalysis.d.ts +1 -1
- package/dist/plugins/DetachedDOMElementAnalysis.js +1 -1
- package/dist/plugins/GlobalVariableAnalysis/BuiltInGlobalVariables.d.ts +2 -2
- package/dist/plugins/GlobalVariableAnalysis/BuiltInGlobalVariables.js +2 -2
- package/dist/plugins/GlobalVariableAnalysis/GlobalVariableAnalysis.d.ts +1 -1
- package/dist/plugins/GlobalVariableAnalysis/GlobalVariableAnalysis.js +1 -2
- package/dist/plugins/ObjectContentAnalysis.d.ts +29 -0
- package/dist/plugins/ObjectContentAnalysis.js +108 -0
- package/dist/plugins/ObjectFanoutAnalysis.d.ts +1 -1
- package/dist/plugins/ObjectFanoutAnalysis.js +1 -1
- package/dist/plugins/ObjectShallowAnalysis.d.ts +1 -1
- package/dist/plugins/ObjectShallowAnalysis.js +1 -1
- package/dist/plugins/ObjectShapeAnalysis.d.ts +1 -1
- package/dist/plugins/ObjectShapeAnalysis.js +1 -1
- package/dist/plugins/ObjectSizeAnalysis.d.ts +1 -1
- package/dist/plugins/ObjectSizeAnalysis.js +1 -1
- package/dist/plugins/ObjectUnboundGrowthAnalysis.d.ts +1 -1
- package/dist/plugins/ObjectUnboundGrowthAnalysis.js +1 -1
- package/dist/plugins/ShapeUnboundGrowthAnalysis.d.ts +1 -1
- package/dist/plugins/ShapeUnboundGrowthAnalysis.js +1 -1
- package/dist/plugins/StringAnalysis.d.ts +1 -1
- package/dist/plugins/StringAnalysis.js +2 -2
- package/dist/plugins/UnmountedReactFiberNodesAnalysis.d.ts +1 -1
- package/dist/plugins/UnmountedReactFiberNodesAnalysis.js +1 -1
- package/package.json +3 -3
package/dist/BaseAnalysis.d.ts
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
|
-
* @emails oncall+ws_labs
|
|
8
7
|
* @format
|
|
8
|
+
* @oncall ws_labs
|
|
9
9
|
*/
|
|
10
10
|
import type { AnyValue } from '@memlab/core';
|
|
11
11
|
import type { HeapAnalysisOptions } from './PluginUtils';
|
package/dist/BaseAnalysis.js
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* This source code is licensed under the MIT license found in the
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*
|
|
8
|
-
* @emails oncall+ws_labs
|
|
9
8
|
* @format
|
|
9
|
+
* @oncall ws_labs
|
|
10
10
|
*/
|
|
11
11
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
12
12
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
@@ -62,7 +62,7 @@ class Analysis {
|
|
|
62
62
|
run(options = PluginUtils_1.default.defaultAnalysisArgs) {
|
|
63
63
|
return __awaiter(this, void 0, void 0, function* () {
|
|
64
64
|
loadScenarioConfig();
|
|
65
|
-
|
|
65
|
+
yield this.process(options);
|
|
66
66
|
});
|
|
67
67
|
}
|
|
68
68
|
/**
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
|
-
* @emails oncall+ws_labs
|
|
8
7
|
* @format
|
|
8
|
+
* @oncall ws_labs
|
|
9
9
|
*/
|
|
10
10
|
import type BaseAnalysis from './BaseAnalysis';
|
|
11
11
|
declare class HeapAnalysisLoader {
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* This source code is licensed under the MIT license found in the
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*
|
|
8
|
-
* @emails oncall+ws_labs
|
|
9
8
|
* @format
|
|
9
|
+
* @oncall ws_labs
|
|
10
10
|
*/
|
|
11
11
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
12
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @format
|
|
8
|
+
* @oncall ws_labs
|
|
9
|
+
*/
|
|
10
|
+
import type { IHeapSnapshot, Optional, IHeapConfig } from '@memlab/core';
|
|
11
|
+
declare class HeapConfig implements IHeapConfig {
|
|
12
|
+
isCliInteractiveMode: boolean;
|
|
13
|
+
currentHeapFile: Optional<string>;
|
|
14
|
+
currentHeap: Optional<IHeapSnapshot>;
|
|
15
|
+
private constructor();
|
|
16
|
+
private static instance;
|
|
17
|
+
static getInstance(): HeapConfig;
|
|
18
|
+
}
|
|
19
|
+
declare const heapConfig: HeapConfig;
|
|
20
|
+
export default heapConfig;
|
|
21
|
+
//# sourceMappingURL=HeapConfig.d.ts.map
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*
|
|
8
|
+
* @format
|
|
9
|
+
* @oncall ws_labs
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const core_1 = require("@memlab/core");
|
|
13
|
+
class HeapConfig {
|
|
14
|
+
constructor() {
|
|
15
|
+
this.isCliInteractiveMode = false;
|
|
16
|
+
this.currentHeap = null;
|
|
17
|
+
this.currentHeapFile = null;
|
|
18
|
+
}
|
|
19
|
+
static getInstance() {
|
|
20
|
+
if (!HeapConfig.instance) {
|
|
21
|
+
HeapConfig.instance = new HeapConfig();
|
|
22
|
+
}
|
|
23
|
+
return HeapConfig.instance;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
HeapConfig.instance = null;
|
|
27
|
+
const heapConfig = HeapConfig.getInstance();
|
|
28
|
+
core_1.config.heapConfig = heapConfig;
|
|
29
|
+
exports.default = heapConfig;
|
package/dist/PluginUtils.d.ts
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
|
-
* @emails oncall+ws_labs
|
|
8
7
|
* @format
|
|
8
|
+
* @oncall ws_labs
|
|
9
9
|
*/
|
|
10
10
|
import type { ParsedArgs } from 'minimist';
|
|
11
11
|
import { IHeapSnapshot, IHeapNode, AnyOptions, IHeapEdge, Nullable, MemLabConfig } from '@memlab/core';
|
|
@@ -31,6 +31,7 @@ declare type PrintNodeOption = {
|
|
|
31
31
|
};
|
|
32
32
|
declare function printNodeListInTerminal(nodeList: IHeapNode[], options?: AnyOptions & PrintNodeOption): void;
|
|
33
33
|
declare function printReferencesInTerminal(edgeList: IHeapEdge[], options?: AnyOptions & PrintNodeOption): void;
|
|
34
|
+
declare function printReferrersInTerminal(edgeList: IHeapEdge[], options?: AnyOptions & PrintNodeOption): void;
|
|
34
35
|
declare function getObjectOutgoingEdgeCount(node: IHeapNode): number;
|
|
35
36
|
/**
|
|
36
37
|
* Get the heap snapshot file's absolute path passed to the hosting heap
|
|
@@ -166,14 +167,36 @@ declare function loadHeapSnapshot(options: HeapAnalysisOptions): Promise<IHeapSn
|
|
|
166
167
|
* * **Examples**:
|
|
167
168
|
* ```typescript
|
|
168
169
|
* import {dumpNodeHeapSnapshot} from '@memlab/core';
|
|
169
|
-
* import {
|
|
170
|
+
* import {getFullHeapFromFile} from '@memlab/heap-analysis';
|
|
170
171
|
*
|
|
171
172
|
* (async function (){
|
|
172
173
|
* const heapFile = dumpNodeHeapSnapshot();
|
|
173
|
-
* const heap = await
|
|
174
|
+
* const heap = await getFullHeapFromFile(heapFile);
|
|
174
175
|
* })();
|
|
175
176
|
* ```
|
|
176
177
|
*/
|
|
178
|
+
declare function getFullHeapFromFile(file: string): Promise<IHeapSnapshot>;
|
|
179
|
+
/**
|
|
180
|
+
* Take a heap snapshot of the current program state
|
|
181
|
+
* and parse it as {@link IHeapSnapshot}. This
|
|
182
|
+
* API also calculates some heap analysis meta data
|
|
183
|
+
* for heap analysis. But this also means slower heap parsing
|
|
184
|
+
* comparing with {@link takeNodeMinimalHeap}.
|
|
185
|
+
*
|
|
186
|
+
* @returns heap representation with heap analysis meta data.
|
|
187
|
+
*
|
|
188
|
+
* * **Examples:**
|
|
189
|
+
* ```typescript
|
|
190
|
+
* import type {IHeapSnapshot} from '@memlab/core';
|
|
191
|
+
* import type {takeNodeFullHeap} from '@memlab/heap-analysis';
|
|
192
|
+
*
|
|
193
|
+
* (async function () {
|
|
194
|
+
* const heap: IHeapSnapshot = await takeNodeFullHeap();
|
|
195
|
+
* })();
|
|
196
|
+
* ```
|
|
197
|
+
*/
|
|
198
|
+
declare function takeNodeFullHeap(): Promise<IHeapSnapshot>;
|
|
199
|
+
/** @deprecated */
|
|
177
200
|
declare function getHeapFromFile(file: string): Promise<IHeapSnapshot>;
|
|
178
201
|
/**
|
|
179
202
|
* When a heap analysis is taking multiple heap snapshots as input for memory
|
|
@@ -261,7 +284,7 @@ declare function aggregateDominatorMetrics(ids: Set<number>, snapshot: IHeapSnap
|
|
|
261
284
|
* * * **Examples**:
|
|
262
285
|
* ```typescript
|
|
263
286
|
* import {dumpNodeHeapSnapshot} from '@memlab/core';
|
|
264
|
-
* import {
|
|
287
|
+
* import {getFullHeapFromFile, getDominatorNodes} from '@memlab/heap-analysis';
|
|
265
288
|
*
|
|
266
289
|
* class TestObject {}
|
|
267
290
|
*
|
|
@@ -271,7 +294,7 @@ declare function aggregateDominatorMetrics(ids: Set<number>, snapshot: IHeapSnap
|
|
|
271
294
|
*
|
|
272
295
|
* // dump the heap of this running JavaScript program
|
|
273
296
|
* const heapFile = dumpNodeHeapSnapshot();
|
|
274
|
-
* const heap = await
|
|
297
|
+
* const heap = await getFullHeapFromFile(heapFile);
|
|
275
298
|
*
|
|
276
299
|
* // find the heap node for TestObject
|
|
277
300
|
* let nodes = [];
|
|
@@ -306,9 +329,12 @@ declare const _default: {
|
|
|
306
329
|
isNodeWorthInspecting: typeof isNodeWorthInspecting;
|
|
307
330
|
loadHeapSnapshot: typeof loadHeapSnapshot;
|
|
308
331
|
getHeapFromFile: typeof getHeapFromFile;
|
|
332
|
+
getFullHeapFromFile: typeof getFullHeapFromFile;
|
|
309
333
|
printNodeListInTerminal: typeof printNodeListInTerminal;
|
|
310
334
|
printReferencesInTerminal: typeof printReferencesInTerminal;
|
|
335
|
+
printReferrersInTerminal: typeof printReferrersInTerminal;
|
|
311
336
|
snapshotMapReduce: typeof snapshotMapReduce;
|
|
337
|
+
takeNodeFullHeap: typeof takeNodeFullHeap;
|
|
312
338
|
};
|
|
313
339
|
export default _default;
|
|
314
340
|
//# sourceMappingURL=PluginUtils.d.ts.map
|
package/dist/PluginUtils.js
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* This source code is licensed under the MIT license found in the
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*
|
|
8
|
-
* @emails oncall+ws_labs
|
|
9
8
|
* @format
|
|
9
|
+
* @oncall ws_labs
|
|
10
10
|
*/
|
|
11
11
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
12
12
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
@@ -24,6 +24,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
24
24
|
const core_1 = require("@memlab/core");
|
|
25
25
|
const chalk_1 = __importDefault(require("chalk"));
|
|
26
26
|
const core_2 = require("@memlab/core");
|
|
27
|
+
const HeapConfig_1 = __importDefault(require("./HeapConfig"));
|
|
27
28
|
const nodeNameBlockList = new Set([
|
|
28
29
|
'(Startup object cache)',
|
|
29
30
|
'(Global handles)',
|
|
@@ -163,6 +164,7 @@ function getHeapObjectString(node) {
|
|
|
163
164
|
return (`${nodeId}${type} ${shapeStr}${colon} ` +
|
|
164
165
|
`${fanout}${comma} ${bytes}${comma} ${refs}`);
|
|
165
166
|
}
|
|
167
|
+
const MAX_NUM_OF_EDGES_TO_PRINT = 50;
|
|
166
168
|
function getReferenceString(edge) {
|
|
167
169
|
const edgeName = chalk_1.default.green(edge.name_or_index);
|
|
168
170
|
const objectInfo = getHeapObjectString(edge.toNode);
|
|
@@ -171,10 +173,39 @@ function getReferenceString(edge) {
|
|
|
171
173
|
function printReferencesInTerminal(edgeList, options = {}) {
|
|
172
174
|
const dot = chalk_1.default.grey('· ');
|
|
173
175
|
const indent = options.indent || '';
|
|
176
|
+
let n = 0;
|
|
174
177
|
for (const edge of edgeList) {
|
|
178
|
+
if (!core_1.config.verbose && n >= MAX_NUM_OF_EDGES_TO_PRINT) {
|
|
179
|
+
break;
|
|
180
|
+
}
|
|
181
|
+
++n;
|
|
175
182
|
const refStr = getReferenceString(edge);
|
|
176
183
|
core_2.info.topLevel(`${indent}${dot}${refStr}`);
|
|
177
184
|
}
|
|
185
|
+
if (n < edgeList.length) {
|
|
186
|
+
core_2.info.lowLevel(`${edgeList.length - n} more references...`);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
function getReferrerString(edge) {
|
|
190
|
+
const edgeName = chalk_1.default.green(edge.name_or_index);
|
|
191
|
+
const objectInfo = getHeapObjectString(edge.fromNode);
|
|
192
|
+
return ` ${objectInfo} --${edgeName}--> `;
|
|
193
|
+
}
|
|
194
|
+
function printReferrersInTerminal(edgeList, options = {}) {
|
|
195
|
+
const dot = chalk_1.default.grey('· ');
|
|
196
|
+
const indent = options.indent || '';
|
|
197
|
+
let n = 0;
|
|
198
|
+
for (const edge of edgeList) {
|
|
199
|
+
if (!core_1.config.verbose && n >= MAX_NUM_OF_EDGES_TO_PRINT) {
|
|
200
|
+
break;
|
|
201
|
+
}
|
|
202
|
+
++n;
|
|
203
|
+
const refStr = getReferrerString(edge);
|
|
204
|
+
core_2.info.topLevel(`${indent}${dot}${refStr}`);
|
|
205
|
+
}
|
|
206
|
+
if (n < edgeList.length) {
|
|
207
|
+
core_2.info.lowLevel(`${edgeList.length - n} more referrers...`);
|
|
208
|
+
}
|
|
178
209
|
}
|
|
179
210
|
function getObjectOutgoingEdgeCount(node) {
|
|
180
211
|
if (node.name === 'Set' || node.name === 'Map') {
|
|
@@ -231,9 +262,6 @@ function getSnapshotFileForAnalysis(options) {
|
|
|
231
262
|
if (args.snapshot) {
|
|
232
263
|
return args.snapshot;
|
|
233
264
|
}
|
|
234
|
-
if (core_1.config.externalSnapshotFilePaths.length > 0) {
|
|
235
|
-
return core_1.config.externalSnapshotFilePaths[core_1.config.externalSnapshotFilePaths.length - 1];
|
|
236
|
-
}
|
|
237
265
|
return core_2.utils.getSingleSnapshotFileForAnalysis();
|
|
238
266
|
}
|
|
239
267
|
/**
|
|
@@ -330,8 +358,19 @@ function getSnapshotDirForAnalysis(options) {
|
|
|
330
358
|
*/
|
|
331
359
|
function loadHeapSnapshot(options) {
|
|
332
360
|
return __awaiter(this, void 0, void 0, function* () {
|
|
333
|
-
|
|
334
|
-
|
|
361
|
+
if (HeapConfig_1.default.isCliInteractiveMode) {
|
|
362
|
+
if (!HeapConfig_1.default.currentHeap) {
|
|
363
|
+
const file = getSnapshotFileForAnalysis(options);
|
|
364
|
+
const heap = yield loadProcessedSnapshot({ file });
|
|
365
|
+
HeapConfig_1.default.currentHeapFile = file;
|
|
366
|
+
HeapConfig_1.default.currentHeap = heap;
|
|
367
|
+
}
|
|
368
|
+
return HeapConfig_1.default.currentHeap;
|
|
369
|
+
}
|
|
370
|
+
else {
|
|
371
|
+
const file = getSnapshotFileForAnalysis(options);
|
|
372
|
+
return loadProcessedSnapshot({ file });
|
|
373
|
+
}
|
|
335
374
|
});
|
|
336
375
|
}
|
|
337
376
|
/**
|
|
@@ -343,14 +382,47 @@ function loadHeapSnapshot(options) {
|
|
|
343
382
|
* * **Examples**:
|
|
344
383
|
* ```typescript
|
|
345
384
|
* import {dumpNodeHeapSnapshot} from '@memlab/core';
|
|
346
|
-
* import {
|
|
385
|
+
* import {getFullHeapFromFile} from '@memlab/heap-analysis';
|
|
347
386
|
*
|
|
348
387
|
* (async function (){
|
|
349
388
|
* const heapFile = dumpNodeHeapSnapshot();
|
|
350
|
-
* const heap = await
|
|
389
|
+
* const heap = await getFullHeapFromFile(heapFile);
|
|
351
390
|
* })();
|
|
352
391
|
* ```
|
|
353
392
|
*/
|
|
393
|
+
function getFullHeapFromFile(file) {
|
|
394
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
395
|
+
return yield loadProcessedSnapshot({ file });
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Take a heap snapshot of the current program state
|
|
400
|
+
* and parse it as {@link IHeapSnapshot}. This
|
|
401
|
+
* API also calculates some heap analysis meta data
|
|
402
|
+
* for heap analysis. But this also means slower heap parsing
|
|
403
|
+
* comparing with {@link takeNodeMinimalHeap}.
|
|
404
|
+
*
|
|
405
|
+
* @returns heap representation with heap analysis meta data.
|
|
406
|
+
*
|
|
407
|
+
* * **Examples:**
|
|
408
|
+
* ```typescript
|
|
409
|
+
* import type {IHeapSnapshot} from '@memlab/core';
|
|
410
|
+
* import type {takeNodeFullHeap} from '@memlab/heap-analysis';
|
|
411
|
+
*
|
|
412
|
+
* (async function () {
|
|
413
|
+
* const heap: IHeapSnapshot = await takeNodeFullHeap();
|
|
414
|
+
* })();
|
|
415
|
+
* ```
|
|
416
|
+
*/
|
|
417
|
+
function takeNodeFullHeap() {
|
|
418
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
419
|
+
const heap = yield (0, core_1.takeNodeMinimalHeap)();
|
|
420
|
+
core_2.analysis.preparePathFinder(heap);
|
|
421
|
+
core_2.info.flush();
|
|
422
|
+
return heap;
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
/** @deprecated */
|
|
354
426
|
function getHeapFromFile(file) {
|
|
355
427
|
return __awaiter(this, void 0, void 0, function* () {
|
|
356
428
|
return yield loadProcessedSnapshot({ file });
|
|
@@ -480,7 +552,7 @@ function aggregateDominatorMetrics(ids, snapshot, checkNodeCb, nodeMetricsCb) {
|
|
|
480
552
|
* * * **Examples**:
|
|
481
553
|
* ```typescript
|
|
482
554
|
* import {dumpNodeHeapSnapshot} from '@memlab/core';
|
|
483
|
-
* import {
|
|
555
|
+
* import {getFullHeapFromFile, getDominatorNodes} from '@memlab/heap-analysis';
|
|
484
556
|
*
|
|
485
557
|
* class TestObject {}
|
|
486
558
|
*
|
|
@@ -490,7 +562,7 @@ function aggregateDominatorMetrics(ids, snapshot, checkNodeCb, nodeMetricsCb) {
|
|
|
490
562
|
*
|
|
491
563
|
* // dump the heap of this running JavaScript program
|
|
492
564
|
* const heapFile = dumpNodeHeapSnapshot();
|
|
493
|
-
* const heap = await
|
|
565
|
+
* const heap = await getFullHeapFromFile(heapFile);
|
|
494
566
|
*
|
|
495
567
|
* // find the heap node for TestObject
|
|
496
568
|
* let nodes = [];
|
|
@@ -543,7 +615,10 @@ exports.default = {
|
|
|
543
615
|
isNodeWorthInspecting,
|
|
544
616
|
loadHeapSnapshot,
|
|
545
617
|
getHeapFromFile,
|
|
618
|
+
getFullHeapFromFile,
|
|
546
619
|
printNodeListInTerminal,
|
|
547
620
|
printReferencesInTerminal,
|
|
621
|
+
printReferrersInTerminal,
|
|
548
622
|
snapshotMapReduce,
|
|
623
|
+
takeNodeFullHeap,
|
|
549
624
|
};
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* This source code is licensed under the MIT license found in the
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*
|
|
8
|
-
* @emails oncall+ws_labs
|
|
9
8
|
* @format
|
|
9
|
+
* @oncall ws_labs
|
|
10
10
|
*/
|
|
11
11
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
12
12
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
@@ -22,11 +22,29 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
22
22
|
};
|
|
23
23
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
24
|
const core_1 = require("@memlab/core");
|
|
25
|
+
const __1 = require("..");
|
|
25
26
|
const HeapAnalysisLoader_1 = __importDefault(require("../HeapAnalysisLoader"));
|
|
26
27
|
beforeEach(() => {
|
|
27
28
|
core_1.config.isTest = true;
|
|
28
29
|
});
|
|
30
|
+
const timeout = 5 * 60 * 1000;
|
|
29
31
|
test('Heap analysis modules can be loaded', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
30
32
|
const heapAnalysisMap = HeapAnalysisLoader_1.default.loadAllAnalysis();
|
|
31
33
|
expect(heapAnalysisMap.size).toBeGreaterThan(0);
|
|
32
|
-
}));
|
|
34
|
+
}), timeout);
|
|
35
|
+
test('takeNodeFullHeap works as expected', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
36
|
+
var _a;
|
|
37
|
+
class TestClass {
|
|
38
|
+
constructor() {
|
|
39
|
+
this.name = 'test';
|
|
40
|
+
this.age = 183;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
44
|
+
const _v = new TestClass();
|
|
45
|
+
const heap = yield (0, __1.takeNodeFullHeap)();
|
|
46
|
+
const node = heap.getAnyObjectWithClassName('TestClass');
|
|
47
|
+
expect((node === null || node === void 0 ? void 0 : node.dominatorNode) != null).toBe(true);
|
|
48
|
+
const size = (_a = node === null || node === void 0 ? void 0 : node.retainedSize) !== null && _a !== void 0 ? _a : 0;
|
|
49
|
+
expect(size > 0).toBe(true);
|
|
50
|
+
}), timeout);
|
|
@@ -14,6 +14,7 @@ const index_1 = require("../index");
|
|
|
14
14
|
beforeEach(() => {
|
|
15
15
|
core_1.config.isTest = true;
|
|
16
16
|
});
|
|
17
|
+
const timeout = 5 * 60 * 1000;
|
|
17
18
|
test('loadHeapSnapshot works as expected', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
18
19
|
let called = false;
|
|
19
20
|
class ExampleAnalysis extends index_1.BaseAnalysis {
|
|
@@ -34,7 +35,7 @@ test('loadHeapSnapshot works as expected', () => __awaiter(void 0, void 0, void
|
|
|
34
35
|
const analysis = new ExampleAnalysis();
|
|
35
36
|
yield analysis.analyzeSnapshotFromFile((0, core_1.dumpNodeHeapSnapshot)());
|
|
36
37
|
expect(called).toBe(true);
|
|
37
|
-
}));
|
|
38
|
+
}), timeout);
|
|
38
39
|
test('analyzeSnapshotFromFile works as expected', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
39
40
|
let called = false;
|
|
40
41
|
const heapFile = (0, core_1.dumpNodeHeapSnapshot)();
|
|
@@ -56,12 +57,12 @@ test('analyzeSnapshotFromFile works as expected', () => __awaiter(void 0, void 0
|
|
|
56
57
|
const analysis = new ExampleAnalysis();
|
|
57
58
|
yield analysis.analyzeSnapshotFromFile(heapFile);
|
|
58
59
|
expect(called).toBe(true);
|
|
59
|
-
}));
|
|
60
|
-
test('
|
|
60
|
+
}), timeout);
|
|
61
|
+
test('getFullHeapFromFile works as expected', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
61
62
|
const heapFile = (0, core_1.dumpNodeHeapSnapshot)();
|
|
62
|
-
const heap = yield (0, index_1.
|
|
63
|
+
const heap = yield (0, index_1.getFullHeapFromFile)(heapFile);
|
|
63
64
|
expect(heap.nodes.length > 0).toBe(true);
|
|
64
|
-
}));
|
|
65
|
+
}), timeout);
|
|
65
66
|
test('getDominatorNodes works as expected', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
66
67
|
class TestObject {
|
|
67
68
|
}
|
|
@@ -71,7 +72,7 @@ test('getDominatorNodes works as expected', () => __awaiter(void 0, void 0, void
|
|
|
71
72
|
const t2 = new TestObject();
|
|
72
73
|
// dump the heap of this running JavaScript program
|
|
73
74
|
const heapFile = (0, core_1.dumpNodeHeapSnapshot)();
|
|
74
|
-
const heap = yield (0, index_1.
|
|
75
|
+
const heap = yield (0, index_1.getFullHeapFromFile)(heapFile);
|
|
75
76
|
// find the heap node for TestObject
|
|
76
77
|
const nodes = [];
|
|
77
78
|
heap.nodes.forEach(node => {
|
|
@@ -82,4 +83,4 @@ test('getDominatorNodes works as expected', () => __awaiter(void 0, void 0, void
|
|
|
82
83
|
// get the dominator nodes
|
|
83
84
|
const dominatorIds = (0, index_1.getDominatorNodes)(new Set(nodes.map(node => node.id)), heap);
|
|
84
85
|
expect(dominatorIds.size).toBeGreaterThan(0);
|
|
85
|
-
}));
|
|
86
|
+
}), timeout);
|
package/dist/index.d.ts
CHANGED
|
@@ -4,12 +4,14 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
|
-
* @emails oncall+ws_labs
|
|
8
7
|
* @format
|
|
8
|
+
* @oncall ws_labs
|
|
9
9
|
*/
|
|
10
10
|
/** @internal */
|
|
11
11
|
export declare function registerPackage(): Promise<void>;
|
|
12
|
-
export declare const getDominatorNodes: (ids: Set<number>, snapshot: import("@memlab/core").IHeapSnapshot) => Set<number>,
|
|
12
|
+
export declare const getDominatorNodes: (ids: Set<number>, snapshot: import("@memlab/core").IHeapSnapshot) => Set<number>,
|
|
13
|
+
/** @deprecated */
|
|
14
|
+
getHeapFromFile: (file: string) => Promise<import("@memlab/core").IHeapSnapshot>, getFullHeapFromFile: (file: string) => Promise<import("@memlab/core").IHeapSnapshot>, getSnapshotDirForAnalysis: (options: import("./PluginUtils").HeapAnalysisOptions) => import("@memlab/core").Nullable<string>, getSnapshotFileForAnalysis: (options: import("./PluginUtils").HeapAnalysisOptions) => string, loadHeapSnapshot: (options: import("./PluginUtils").HeapAnalysisOptions) => Promise<import("@memlab/core").IHeapSnapshot>, snapshotMapReduce: <T1, T2>(mapCallback: (snapshot: import("@memlab/core").IHeapSnapshot, i: number, file: string) => T1, reduceCallback: (results: T1[]) => T2, options: import("./PluginUtils").HeapAnalysisOptions) => Promise<T2>, takeNodeFullHeap: () => Promise<import("@memlab/core").IHeapSnapshot>;
|
|
13
15
|
export type { HeapAnalysisOptions } from './PluginUtils';
|
|
14
16
|
export { default as BaseAnalysis } from './BaseAnalysis';
|
|
15
17
|
export { default as DetachedDOMElementAnalysis } from './plugins/DetachedDOMElementAnalysis';
|
|
@@ -26,4 +28,6 @@ export { default as StringAnalysis } from './plugins/StringAnalysis';
|
|
|
26
28
|
export { default as PluginUtils } from './PluginUtils';
|
|
27
29
|
/** @internal */
|
|
28
30
|
export { default as heapAnalysisLoader } from './HeapAnalysisLoader';
|
|
31
|
+
/** @internal */
|
|
32
|
+
export { default as heapConfig } from './HeapConfig';
|
|
29
33
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* This source code is licensed under the MIT license found in the
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*
|
|
8
|
-
* @emails oncall+ws_labs
|
|
9
8
|
* @format
|
|
9
|
+
* @oncall ws_labs
|
|
10
10
|
*/
|
|
11
11
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
12
12
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
@@ -21,7 +21,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
21
21
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
22
22
|
};
|
|
23
23
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
-
exports.heapAnalysisLoader = exports.PluginUtils = exports.StringAnalysis = exports.ObjectUnboundGrowthAnalysis = exports.ObjectShapeAnalysis = exports.ObjectFanoutAnalysis = exports.ShapeUnboundGrowthAnalysis = exports.ObjectSizeAnalysis = exports.ObjectShallowAnalysis = exports.CollectionsHoldingStaleAnalysis = exports.GlobalVariableAnalysis = exports.DetachedDOMElementAnalysis = exports.BaseAnalysis = exports.snapshotMapReduce = exports.loadHeapSnapshot = exports.getSnapshotFileForAnalysis = exports.getSnapshotDirForAnalysis = exports.getHeapFromFile = exports.getDominatorNodes = exports.registerPackage = void 0;
|
|
24
|
+
exports.heapConfig = exports.heapAnalysisLoader = exports.PluginUtils = exports.StringAnalysis = exports.ObjectUnboundGrowthAnalysis = exports.ObjectShapeAnalysis = exports.ObjectFanoutAnalysis = exports.ShapeUnboundGrowthAnalysis = exports.ObjectSizeAnalysis = exports.ObjectShallowAnalysis = exports.CollectionsHoldingStaleAnalysis = exports.GlobalVariableAnalysis = exports.DetachedDOMElementAnalysis = exports.BaseAnalysis = exports.takeNodeFullHeap = exports.snapshotMapReduce = exports.loadHeapSnapshot = exports.getSnapshotFileForAnalysis = exports.getSnapshotDirForAnalysis = exports.getFullHeapFromFile = exports.getHeapFromFile = exports.getDominatorNodes = exports.registerPackage = void 0;
|
|
25
25
|
const path_1 = __importDefault(require("path"));
|
|
26
26
|
const core_1 = require("@memlab/core");
|
|
27
27
|
/** @internal */
|
|
@@ -32,7 +32,9 @@ function registerPackage() {
|
|
|
32
32
|
}
|
|
33
33
|
exports.registerPackage = registerPackage;
|
|
34
34
|
const PluginUtils_1 = __importDefault(require("./PluginUtils"));
|
|
35
|
-
exports.getDominatorNodes = PluginUtils_1.default.getDominatorNodes,
|
|
35
|
+
exports.getDominatorNodes = PluginUtils_1.default.getDominatorNodes,
|
|
36
|
+
/** @deprecated */
|
|
37
|
+
exports.getHeapFromFile = PluginUtils_1.default.getHeapFromFile, exports.getFullHeapFromFile = PluginUtils_1.default.getFullHeapFromFile, exports.getSnapshotDirForAnalysis = PluginUtils_1.default.getSnapshotDirForAnalysis, exports.getSnapshotFileForAnalysis = PluginUtils_1.default.getSnapshotFileForAnalysis, exports.loadHeapSnapshot = PluginUtils_1.default.loadHeapSnapshot, exports.snapshotMapReduce = PluginUtils_1.default.snapshotMapReduce, exports.takeNodeFullHeap = PluginUtils_1.default.takeNodeFullHeap;
|
|
36
38
|
var BaseAnalysis_1 = require("./BaseAnalysis");
|
|
37
39
|
Object.defineProperty(exports, "BaseAnalysis", { enumerable: true, get: function () { return __importDefault(BaseAnalysis_1).default; } });
|
|
38
40
|
var DetachedDOMElementAnalysis_1 = require("./plugins/DetachedDOMElementAnalysis");
|
|
@@ -61,3 +63,6 @@ Object.defineProperty(exports, "PluginUtils", { enumerable: true, get: function
|
|
|
61
63
|
/** @internal */
|
|
62
64
|
var HeapAnalysisLoader_1 = require("./HeapAnalysisLoader");
|
|
63
65
|
Object.defineProperty(exports, "heapAnalysisLoader", { enumerable: true, get: function () { return __importDefault(HeapAnalysisLoader_1).default; } });
|
|
66
|
+
/** @internal */
|
|
67
|
+
var HeapConfig_1 = require("./HeapConfig");
|
|
68
|
+
Object.defineProperty(exports, "heapConfig", { enumerable: true, get: function () { return __importDefault(HeapConfig_1).default; } });
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @format
|
|
8
|
+
* @oncall ws_labs
|
|
9
|
+
*/
|
|
10
|
+
import type { ParsedArgs } from 'minimist';
|
|
11
|
+
import type { MemLabConfig } from '@memlab/core';
|
|
12
|
+
import { BaseOption } from '@memlab/core';
|
|
13
|
+
export default class HeapAnalysisNodeIdOption extends BaseOption {
|
|
14
|
+
getOptionName(): string;
|
|
15
|
+
getDescription(): string;
|
|
16
|
+
getExampleValues(): string[];
|
|
17
|
+
parse(config: MemLabConfig, args: ParsedArgs): Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=HeapAnalysisNodeIdOption.d.ts.map
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*
|
|
8
|
+
* @format
|
|
9
|
+
* @oncall ws_labs
|
|
10
|
+
*/
|
|
11
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
12
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
13
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
14
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
15
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
16
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
17
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
const core_1 = require("@memlab/core");
|
|
22
|
+
class HeapAnalysisNodeIdOption extends core_1.BaseOption {
|
|
23
|
+
getOptionName() {
|
|
24
|
+
return 'node-id';
|
|
25
|
+
}
|
|
26
|
+
getDescription() {
|
|
27
|
+
return 'set heap node ID';
|
|
28
|
+
}
|
|
29
|
+
getExampleValues() {
|
|
30
|
+
return ['94435', '@94435'];
|
|
31
|
+
}
|
|
32
|
+
parse(config, args) {
|
|
33
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
34
|
+
const optionName = this.getOptionName();
|
|
35
|
+
const optionValue = args[optionName];
|
|
36
|
+
if (optionValue) {
|
|
37
|
+
if (typeof optionValue === 'string' && optionValue.startsWith('@')) {
|
|
38
|
+
args[optionName] = optionValue.slice(1);
|
|
39
|
+
}
|
|
40
|
+
config.focusFiberNodeId = Number(args[optionName]);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
exports.default = HeapAnalysisNodeIdOption;
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
|
-
* @emails oncall+ws_labs
|
|
8
7
|
* @format
|
|
8
|
+
* @oncall ws_labs
|
|
9
9
|
*/
|
|
10
10
|
import type { ParsedArgs } from 'minimist';
|
|
11
11
|
import { BaseOption, MemLabConfig } from '@memlab/core';
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* This source code is licensed under the MIT license found in the
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*
|
|
8
|
-
* @emails oncall+ws_labs
|
|
9
8
|
* @format
|
|
9
|
+
* @oncall ws_labs
|
|
10
10
|
*/
|
|
11
11
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
12
12
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
|
-
* @emails oncall+ws_labs
|
|
8
7
|
* @format
|
|
8
|
+
* @oncall ws_labs
|
|
9
9
|
*/
|
|
10
10
|
import type { ParsedArgs } from 'minimist';
|
|
11
11
|
import { BaseOption, MemLabConfig } from '@memlab/core';
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* This source code is licensed under the MIT license found in the
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*
|
|
8
|
-
* @emails oncall+ws_labs
|
|
9
8
|
* @format
|
|
9
|
+
* @oncall ws_labs
|
|
10
10
|
*/
|
|
11
11
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
12
12
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
|
-
* @emails oncall+ws_labs
|
|
8
7
|
* @format
|
|
8
|
+
* @oncall ws_labs
|
|
9
9
|
*/
|
|
10
10
|
import type { HeapAnalysisOptions } from '../PluginUtils';
|
|
11
11
|
import { BaseOption } from '@memlab/core';
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* This source code is licensed under the MIT license found in the
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*
|
|
8
|
-
* @emails oncall+ws_labs
|
|
9
8
|
* @format
|
|
9
|
+
* @oncall ws_labs
|
|
10
10
|
*/
|
|
11
11
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
12
12
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
|
-
* @emails oncall+ws_labs
|
|
8
7
|
* @format
|
|
8
|
+
* @oncall ws_labs
|
|
9
9
|
*/
|
|
10
10
|
import type { HeapAnalysisOptions } from '../PluginUtils';
|
|
11
11
|
import type { IHeapNode } from '@memlab/core';
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* This source code is licensed under the MIT license found in the
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*
|
|
8
|
-
* @emails oncall+ws_labs
|
|
9
8
|
* @format
|
|
9
|
+
* @oncall ws_labs
|
|
10
10
|
*/
|
|
11
11
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
12
12
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
|
-
* @emails oncall+ws_labs
|
|
8
|
-
* @lightSyntaxTransform
|
|
9
7
|
* @format
|
|
8
|
+
* @lightSyntaxTransform
|
|
9
|
+
* @oncall ws_labs
|
|
10
10
|
*/
|
|
11
11
|
declare const _default: Set<string>;
|
|
12
12
|
export default _default;
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
* This source code is licensed under the MIT license found in the
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*
|
|
8
|
-
* @emails oncall+ws_labs
|
|
9
|
-
* @lightSyntaxTransform
|
|
10
8
|
* @format
|
|
9
|
+
* @lightSyntaxTransform
|
|
10
|
+
* @oncall ws_labs
|
|
11
11
|
*/
|
|
12
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
13
|
exports.default = new Set([
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
|
-
* @emails oncall+ws_labs
|
|
8
7
|
* @format
|
|
8
|
+
* @oncall ws_labs
|
|
9
9
|
*/
|
|
10
10
|
import type { HeapAnalysisOptions } from '../../PluginUtils';
|
|
11
11
|
import { BaseOption } from '@memlab/core';
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* This source code is licensed under the MIT license found in the
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*
|
|
8
|
-
* @emails oncall+ws_labs
|
|
9
8
|
* @format
|
|
9
|
+
* @oncall ws_labs
|
|
10
10
|
*/
|
|
11
11
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
12
12
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
@@ -71,7 +71,6 @@ class GlobalVariableAnalysis extends BaseAnalysis_1.default {
|
|
|
71
71
|
}
|
|
72
72
|
/** @internal */
|
|
73
73
|
getGlobalVariables(snapshot) {
|
|
74
|
-
// rank heap objects based on fanout
|
|
75
74
|
const ret = [];
|
|
76
75
|
const processNode = (node) => {
|
|
77
76
|
if (!node.name.startsWith('Window ')) {
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @format
|
|
8
|
+
* @oncall ws_labs
|
|
9
|
+
*/
|
|
10
|
+
import type { HeapAnalysisOptions } from '../PluginUtils';
|
|
11
|
+
import { BaseOption } from '@memlab/core';
|
|
12
|
+
import BaseAnalysis from '../BaseAnalysis';
|
|
13
|
+
declare class GlobalVariableAnalysis extends BaseAnalysis {
|
|
14
|
+
getCommandName(): string;
|
|
15
|
+
/** @internal */
|
|
16
|
+
getDescription(): string;
|
|
17
|
+
/** @internal */
|
|
18
|
+
getOptions(): BaseOption[];
|
|
19
|
+
/** @internal */
|
|
20
|
+
process(options: HeapAnalysisOptions): Promise<void>;
|
|
21
|
+
/** @internal */
|
|
22
|
+
analyzeSnapshotsInDirectory(directory: string): Promise<void>;
|
|
23
|
+
/** @internal */
|
|
24
|
+
private getObjectProperties;
|
|
25
|
+
/** @internal */
|
|
26
|
+
private getObjectReferrerEdges;
|
|
27
|
+
}
|
|
28
|
+
export default GlobalVariableAnalysis;
|
|
29
|
+
//# sourceMappingURL=ObjectContentAnalysis.d.ts.map
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*
|
|
8
|
+
* @format
|
|
9
|
+
* @oncall ws_labs
|
|
10
|
+
*/
|
|
11
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
12
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
13
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
14
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
15
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
16
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
17
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
21
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
22
|
+
};
|
|
23
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
25
|
+
const core_1 = require("@memlab/core");
|
|
26
|
+
const HeapAnalysisNodeIdOption_1 = __importDefault(require("../options/HeapAnalysisNodeIdOption"));
|
|
27
|
+
const HeapAnalysisSnapshotFileOption_1 = __importDefault(require("../options/HeapAnalysisSnapshotFileOption"));
|
|
28
|
+
const BaseAnalysis_1 = __importDefault(require("../BaseAnalysis"));
|
|
29
|
+
const PluginUtils_1 = __importDefault(require("../PluginUtils"));
|
|
30
|
+
class GlobalVariableAnalysis extends BaseAnalysis_1.default {
|
|
31
|
+
getCommandName() {
|
|
32
|
+
return 'object';
|
|
33
|
+
}
|
|
34
|
+
/** @internal */
|
|
35
|
+
getDescription() {
|
|
36
|
+
return 'Get properties inside an object';
|
|
37
|
+
}
|
|
38
|
+
/** @internal */
|
|
39
|
+
getOptions() {
|
|
40
|
+
return [new HeapAnalysisSnapshotFileOption_1.default(), new HeapAnalysisNodeIdOption_1.default()];
|
|
41
|
+
}
|
|
42
|
+
/** @internal */
|
|
43
|
+
process(options) {
|
|
44
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
45
|
+
const snapshot = yield PluginUtils_1.default.loadHeapSnapshot(options);
|
|
46
|
+
const nodeId = core_1.config.focusFiberNodeId;
|
|
47
|
+
const node = snapshot.getNodeById(nodeId);
|
|
48
|
+
if (!node) {
|
|
49
|
+
core_1.info.error(`Object @${nodeId} is not found.`);
|
|
50
|
+
core_1.info.lowLevel(`Specify an object by --node-id`);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
// print object info
|
|
54
|
+
const id = chalk_1.default.grey(`@${node.id}`);
|
|
55
|
+
core_1.info.topLevel(`Heap node (${node.type}) ${id}`);
|
|
56
|
+
const name = chalk_1.default.grey(`${node.name}`);
|
|
57
|
+
core_1.info.topLevel(` name: ${name}`);
|
|
58
|
+
const numReferences = chalk_1.default.grey(`${node.edge_count}`);
|
|
59
|
+
core_1.info.topLevel(` # of references: ${numReferences}`);
|
|
60
|
+
const numReferrers = chalk_1.default.grey(`${node.referrers.length}`);
|
|
61
|
+
core_1.info.topLevel(` # of referrers: ${numReferrers}`);
|
|
62
|
+
const selfSize = chalk_1.default.grey(`${node.self_size}`);
|
|
63
|
+
core_1.info.topLevel(` shallow size: ${selfSize}`);
|
|
64
|
+
const retainedSize = chalk_1.default.grey(`${node.retainedSize}`);
|
|
65
|
+
core_1.info.topLevel(` retained size: ${retainedSize}`);
|
|
66
|
+
const dominatorNode = node.dominatorNode;
|
|
67
|
+
if (dominatorNode) {
|
|
68
|
+
const dominatorNodeId = chalk_1.default.grey(`@${dominatorNode.id}`);
|
|
69
|
+
core_1.info.topLevel(` dominator node: ${dominatorNodeId}`);
|
|
70
|
+
}
|
|
71
|
+
// print object references
|
|
72
|
+
core_1.info.topLevel('\n' + chalk_1.default.bold('REFERENCES:'));
|
|
73
|
+
let list = this.getObjectProperties(snapshot, node);
|
|
74
|
+
PluginUtils_1.default.printReferencesInTerminal(list);
|
|
75
|
+
core_1.info.topLevel('\n' + chalk_1.default.bold('REFERRERS:'));
|
|
76
|
+
// print object referrers
|
|
77
|
+
list = this.getObjectReferrerEdges(snapshot, node);
|
|
78
|
+
PluginUtils_1.default.printReferrersInTerminal(list);
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
/** @internal */
|
|
82
|
+
analyzeSnapshotsInDirectory(directory) {
|
|
83
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
84
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
85
|
+
const d = directory;
|
|
86
|
+
throw core_1.utils.haltOrThrow(`${this.constructor.name} does not support analyzeSnapshotsInDirectory`);
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
/** @internal */
|
|
90
|
+
getObjectProperties(snapshot, node) {
|
|
91
|
+
const ret = [];
|
|
92
|
+
const refs = node.references;
|
|
93
|
+
for (const edge of refs) {
|
|
94
|
+
ret.push(edge);
|
|
95
|
+
}
|
|
96
|
+
return ret;
|
|
97
|
+
}
|
|
98
|
+
/** @internal */
|
|
99
|
+
getObjectReferrerEdges(snapshot, node) {
|
|
100
|
+
const ret = [];
|
|
101
|
+
const refs = node.referrers;
|
|
102
|
+
for (const edge of refs) {
|
|
103
|
+
ret.push(edge);
|
|
104
|
+
}
|
|
105
|
+
return ret;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
exports.default = GlobalVariableAnalysis;
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
|
-
* @emails oncall+ws_labs
|
|
8
7
|
* @format
|
|
8
|
+
* @oncall ws_labs
|
|
9
9
|
*/
|
|
10
10
|
import type { HeapAnalysisOptions } from '../PluginUtils';
|
|
11
11
|
import { BaseOption } from '@memlab/core';
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* This source code is licensed under the MIT license found in the
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*
|
|
8
|
-
* @emails oncall+ws_labs
|
|
9
8
|
* @format
|
|
9
|
+
* @oncall ws_labs
|
|
10
10
|
*/
|
|
11
11
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
12
12
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
|
-
* @emails oncall+ws_labs
|
|
8
7
|
* @format
|
|
8
|
+
* @oncall ws_labs
|
|
9
9
|
*/
|
|
10
10
|
import type { HeapAnalysisOptions } from '../PluginUtils';
|
|
11
11
|
import { BaseOption } from '@memlab/core';
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* This source code is licensed under the MIT license found in the
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*
|
|
8
|
-
* @emails oncall+ws_labs
|
|
9
8
|
* @format
|
|
9
|
+
* @oncall ws_labs
|
|
10
10
|
*/
|
|
11
11
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
12
12
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
|
-
* @emails oncall+ws_labs
|
|
8
7
|
* @format
|
|
8
|
+
* @oncall ws_labs
|
|
9
9
|
*/
|
|
10
10
|
import type { HeapAnalysisOptions } from '../PluginUtils';
|
|
11
11
|
import { BaseOption } from '@memlab/core';
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* This source code is licensed under the MIT license found in the
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*
|
|
8
|
-
* @emails oncall+ws_labs
|
|
9
8
|
* @format
|
|
9
|
+
* @oncall ws_labs
|
|
10
10
|
*/
|
|
11
11
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
12
12
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
|
-
* @emails oncall+ws_labs
|
|
8
7
|
* @format
|
|
8
|
+
* @oncall ws_labs
|
|
9
9
|
*/
|
|
10
10
|
import type { HeapAnalysisOptions } from '../PluginUtils';
|
|
11
11
|
import { BaseOption } from '@memlab/core';
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* This source code is licensed under the MIT license found in the
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*
|
|
8
|
-
* @emails oncall+ws_labs
|
|
9
8
|
* @format
|
|
9
|
+
* @oncall ws_labs
|
|
10
10
|
*/
|
|
11
11
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
12
12
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
|
-
* @emails oncall+ws_labs
|
|
8
7
|
* @format
|
|
8
|
+
* @oncall ws_labs
|
|
9
9
|
*/
|
|
10
10
|
import type { HeapAnalysisOptions } from '../PluginUtils';
|
|
11
11
|
import { BaseOption } from '@memlab/core';
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* This source code is licensed under the MIT license found in the
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*
|
|
8
|
-
* @emails oncall+ws_labs
|
|
9
8
|
* @format
|
|
9
|
+
* @oncall ws_labs
|
|
10
10
|
*/
|
|
11
11
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
12
12
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
|
-
* @emails oncall+ws_labs
|
|
8
7
|
* @format
|
|
8
|
+
* @oncall ws_labs
|
|
9
9
|
*/
|
|
10
10
|
import type { HeapAnalysisOptions } from '../PluginUtils';
|
|
11
11
|
import { BaseOption } from '@memlab/core';
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* This source code is licensed under the MIT license found in the
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*
|
|
8
|
-
* @emails oncall+ws_labs
|
|
9
8
|
* @format
|
|
9
|
+
* @oncall ws_labs
|
|
10
10
|
*/
|
|
11
11
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
12
12
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
|
-
* @emails oncall+ws_labs
|
|
8
7
|
* @format
|
|
8
|
+
* @oncall ws_labs
|
|
9
9
|
*/
|
|
10
10
|
import type { HeapAnalysisOptions } from '../PluginUtils';
|
|
11
11
|
import { BaseOption } from '@memlab/core';
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* This source code is licensed under the MIT license found in the
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*
|
|
8
|
-
* @emails oncall+ws_labs
|
|
9
8
|
* @format
|
|
9
|
+
* @oncall ws_labs
|
|
10
10
|
*/
|
|
11
11
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
12
12
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
@@ -60,7 +60,7 @@ class StringAnalysis extends BaseAnalysis_1.default {
|
|
|
60
60
|
* @internal
|
|
61
61
|
*/
|
|
62
62
|
getDescription() {
|
|
63
|
-
return '
|
|
63
|
+
return 'Find duplicated string instances in heap';
|
|
64
64
|
}
|
|
65
65
|
/** @internal */
|
|
66
66
|
getOptions() {
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
|
-
* @emails oncall+ws_labs
|
|
8
7
|
* @format
|
|
8
|
+
* @oncall ws_labs
|
|
9
9
|
*/
|
|
10
10
|
import type { HeapAnalysisOptions } from '../PluginUtils';
|
|
11
11
|
import { BaseOption } from '@memlab/core';
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* This source code is licensed under the MIT license found in the
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*
|
|
8
|
-
* @emails oncall+ws_labs
|
|
9
8
|
* @format
|
|
9
|
+
* @oncall ws_labs
|
|
10
10
|
*/
|
|
11
11
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
12
12
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memlab/heap-analysis",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.9",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "heap analysis plugins for memlab",
|
|
6
6
|
"author": "Liang Gong <lgong@fb.com>",
|
|
@@ -19,8 +19,8 @@
|
|
|
19
19
|
"dist"
|
|
20
20
|
],
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@memlab/core": "^1.1.
|
|
23
|
-
"@memlab/e2e": "^1.0.
|
|
22
|
+
"@memlab/core": "^1.1.10",
|
|
23
|
+
"@memlab/e2e": "^1.0.11",
|
|
24
24
|
"ansi": "^0.3.1",
|
|
25
25
|
"babar": "^0.2.0",
|
|
26
26
|
"chalk": "^4.0.0",
|