@memlab/heap-analysis 1.0.14 → 1.0.16
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 +44 -13
- package/dist/BaseAnalysis.js +60 -12
- package/dist/PluginUtils.d.ts +21 -0
- package/dist/index.d.ts +1 -1
- package/dist/plugins/CollectionUnboundGrowthAnalysis.d.ts +2 -2
- package/dist/plugins/CollectionsHoldingStaleAnalysis.d.ts +2 -2
- package/dist/plugins/DetachedDOMElementAnalysis.d.ts +2 -2
- package/dist/plugins/GlobalVariableAnalysis/GlobalVariableAnalysis.d.ts +2 -2
- package/dist/plugins/ObjectContentAnalysis.d.ts +2 -2
- package/dist/plugins/ObjectFanoutAnalysis.d.ts +2 -2
- package/dist/plugins/ObjectShallowAnalysis.d.ts +2 -2
- package/dist/plugins/ObjectShapeAnalysis.d.ts +13 -3
- package/dist/plugins/ObjectShapeAnalysis.js +126 -1
- package/dist/plugins/ObjectSizeAnalysis.d.ts +2 -2
- package/dist/plugins/ObjectUnboundGrowthAnalysis.d.ts +6 -3
- package/dist/plugins/ObjectUnboundGrowthAnalysis.js +142 -1
- package/dist/plugins/ShapeUnboundGrowthAnalysis.d.ts +2 -2
- package/dist/plugins/StringAnalysis.d.ts +2 -2
- package/dist/plugins/UnmountedReactFiberNodesAnalysis.d.ts +2 -2
- package/package.json +2 -2
package/dist/BaseAnalysis.d.ts
CHANGED
|
@@ -7,9 +7,8 @@
|
|
|
7
7
|
* @format
|
|
8
8
|
* @oncall web_perf_infra
|
|
9
9
|
*/
|
|
10
|
-
import type { AnyValue } from '@memlab/core';
|
|
11
|
-
import type { HeapAnalysisOptions } from './PluginUtils';
|
|
12
|
-
import { BaseOption } from '@memlab/core';
|
|
10
|
+
import type { AnyValue, BaseOption } from '@memlab/core';
|
|
11
|
+
import type { AnalyzeSnapshotResult, HeapAnalysisOptions, RunHeapAnalysisOptions } from './PluginUtils';
|
|
13
12
|
declare abstract class Analysis {
|
|
14
13
|
process(_options: HeapAnalysisOptions): Promise<void>;
|
|
15
14
|
/**
|
|
@@ -27,33 +26,65 @@ declare abstract class Analysis {
|
|
|
27
26
|
/**
|
|
28
27
|
* Run heap analysis for a single heap snapshot file
|
|
29
28
|
* @param file the absolute path of a `.heapsnapshot` file.
|
|
30
|
-
* @
|
|
31
|
-
*
|
|
32
|
-
*
|
|
29
|
+
* @param options optional configuration for the heap analysis run
|
|
30
|
+
* @returns this API returns {@link AnalyzeSnapshotResult}, which contains
|
|
31
|
+
* the logging file of analysis console output. Alternatively, to get more
|
|
32
|
+
* structured analysis results, check out the documentation of the hosting
|
|
33
|
+
* heap analysis class and call the analysis-specific API to get results
|
|
34
|
+
* after calling this method.
|
|
33
35
|
* * **Example**:
|
|
34
36
|
* ```typescript
|
|
35
37
|
* const analysis = new StringAnalysis();
|
|
36
|
-
*
|
|
38
|
+
* // analysis console output is saved in result.analysisOutputFile
|
|
39
|
+
* const result = await analysis.analyzeSnapshotFromFile(snapshotFile);
|
|
40
|
+
* // query analysis-specific and structured results
|
|
37
41
|
* const stringPatterns = analysis.getTopDuplicatedStringsInCount();
|
|
38
42
|
* ```
|
|
43
|
+
* Additionally, you can specify a working directory to where
|
|
44
|
+
* the intermediate, logging, and final output files will be dumped:
|
|
45
|
+
* ```typescript
|
|
46
|
+
* const analysis = new StringAnalysis();
|
|
47
|
+
* // analysis console output is saved in result.analysisOutputFile
|
|
48
|
+
* // which is inside the specified working directory
|
|
49
|
+
* const result = await analysis.analyzeSnapshotFromFile(snapshotFile, {
|
|
50
|
+
* // if the specified directory doesn't exist, memlab will create it
|
|
51
|
+
* workDir: '/tmp/your/work/dir',
|
|
52
|
+
* });
|
|
53
|
+
* ```
|
|
39
54
|
*/
|
|
40
|
-
analyzeSnapshotFromFile(file: string): Promise<
|
|
55
|
+
analyzeSnapshotFromFile(file: string, options?: RunHeapAnalysisOptions): Promise<AnalyzeSnapshotResult>;
|
|
41
56
|
/**
|
|
42
57
|
* Run heap analysis for a series of heap snapshot files
|
|
43
58
|
* @param directory the absolute path of the directory holding a series of
|
|
44
59
|
* `.heapsnapshot` files, all snapshot files will be loaded and analyzed
|
|
45
60
|
* in the alphanumerically ascending order of those snapshot file names.
|
|
46
|
-
* @
|
|
47
|
-
*
|
|
48
|
-
*
|
|
61
|
+
* @param options optional configuration for the heap analysis run
|
|
62
|
+
* @returns this API returns {@link AnalyzeSnapshotResult}, which contains
|
|
63
|
+
* the logging file of analysis console output. Alternatively, to get more
|
|
64
|
+
* structured analysis results, check out the documentation of the hosting
|
|
65
|
+
* heap analysis class and call the analysis-specific API to get results
|
|
66
|
+
* after calling this method.
|
|
49
67
|
* * **Example**:
|
|
50
68
|
* ```typescript
|
|
51
69
|
* const analysis = new ShapeUnboundGrowthAnalysis();
|
|
52
|
-
*
|
|
70
|
+
* // analysis console output is saved in result.analysisOutputFile
|
|
71
|
+
* const result = await analysis.analyzeSnapshotsInDirectory(snapshotDirectory);
|
|
72
|
+
* // query analysis-specific and structured results
|
|
53
73
|
* const shapes = analysis.getShapesWithUnboundGrowth();
|
|
54
74
|
* ```
|
|
75
|
+
* * Additionally, you can specify a working directory to where
|
|
76
|
+
* the intermediate, logging, and final output files will be dumped:
|
|
77
|
+
* ```typescript
|
|
78
|
+
* const analysis = new ShapeUnboundGrowthAnalysis();
|
|
79
|
+
* // analysis console output is saved in result.analysisOutputFile
|
|
80
|
+
* // which is inside the specified working directory
|
|
81
|
+
* const result = await analysis.analyzeSnapshotsInDirectory(snapshotDirectory, {
|
|
82
|
+
* // if the specified directory doesn't exist, memlab will create it
|
|
83
|
+
* workDir: '/tmp/your/work/dir',
|
|
84
|
+
* });
|
|
85
|
+
* ```
|
|
55
86
|
*/
|
|
56
|
-
analyzeSnapshotsInDirectory(directory: string): Promise<
|
|
87
|
+
analyzeSnapshotsInDirectory(directory: string, options?: RunHeapAnalysisOptions): Promise<AnalyzeSnapshotResult>;
|
|
57
88
|
}
|
|
58
89
|
/**
|
|
59
90
|
*
|
package/dist/BaseAnalysis.js
CHANGED
|
@@ -68,25 +68,49 @@ class Analysis {
|
|
|
68
68
|
/**
|
|
69
69
|
* Run heap analysis for a single heap snapshot file
|
|
70
70
|
* @param file the absolute path of a `.heapsnapshot` file.
|
|
71
|
-
* @
|
|
72
|
-
*
|
|
73
|
-
*
|
|
71
|
+
* @param options optional configuration for the heap analysis run
|
|
72
|
+
* @returns this API returns {@link AnalyzeSnapshotResult}, which contains
|
|
73
|
+
* the logging file of analysis console output. Alternatively, to get more
|
|
74
|
+
* structured analysis results, check out the documentation of the hosting
|
|
75
|
+
* heap analysis class and call the analysis-specific API to get results
|
|
76
|
+
* after calling this method.
|
|
74
77
|
* * **Example**:
|
|
75
78
|
* ```typescript
|
|
76
79
|
* const analysis = new StringAnalysis();
|
|
77
|
-
*
|
|
80
|
+
* // analysis console output is saved in result.analysisOutputFile
|
|
81
|
+
* const result = await analysis.analyzeSnapshotFromFile(snapshotFile);
|
|
82
|
+
* // query analysis-specific and structured results
|
|
78
83
|
* const stringPatterns = analysis.getTopDuplicatedStringsInCount();
|
|
79
84
|
* ```
|
|
85
|
+
* Additionally, you can specify a working directory to where
|
|
86
|
+
* the intermediate, logging, and final output files will be dumped:
|
|
87
|
+
* ```typescript
|
|
88
|
+
* const analysis = new StringAnalysis();
|
|
89
|
+
* // analysis console output is saved in result.analysisOutputFile
|
|
90
|
+
* // which is inside the specified working directory
|
|
91
|
+
* const result = await analysis.analyzeSnapshotFromFile(snapshotFile, {
|
|
92
|
+
* // if the specified directory doesn't exist, memlab will create it
|
|
93
|
+
* workDir: '/tmp/your/work/dir',
|
|
94
|
+
* });
|
|
95
|
+
* ```
|
|
80
96
|
*/
|
|
81
|
-
analyzeSnapshotFromFile(file) {
|
|
97
|
+
analyzeSnapshotFromFile(file, options = {}) {
|
|
82
98
|
return __awaiter(this, void 0, void 0, function* () {
|
|
83
|
-
|
|
99
|
+
if (options.workDir) {
|
|
100
|
+
// set and init the new work dir
|
|
101
|
+
core_1.config.defaultFileManagerOption = options;
|
|
102
|
+
}
|
|
103
|
+
const analysisOutputFile = core_1.fileManager.initNewHeapAnalysisLogFile();
|
|
104
|
+
core_1.info.registerLogFile(analysisOutputFile);
|
|
105
|
+
yield this.process({
|
|
84
106
|
args: {
|
|
85
107
|
_: [],
|
|
86
108
|
snapshot: file,
|
|
87
109
|
'snapshot-dir': '<MUST_PROVIDE_SNAPSHOT_DIR>',
|
|
88
110
|
},
|
|
89
111
|
});
|
|
112
|
+
core_1.info.unregisterLogFile(analysisOutputFile);
|
|
113
|
+
return { analysisOutputFile };
|
|
90
114
|
});
|
|
91
115
|
}
|
|
92
116
|
/**
|
|
@@ -94,25 +118,49 @@ class Analysis {
|
|
|
94
118
|
* @param directory the absolute path of the directory holding a series of
|
|
95
119
|
* `.heapsnapshot` files, all snapshot files will be loaded and analyzed
|
|
96
120
|
* in the alphanumerically ascending order of those snapshot file names.
|
|
97
|
-
* @
|
|
98
|
-
*
|
|
99
|
-
*
|
|
121
|
+
* @param options optional configuration for the heap analysis run
|
|
122
|
+
* @returns this API returns {@link AnalyzeSnapshotResult}, which contains
|
|
123
|
+
* the logging file of analysis console output. Alternatively, to get more
|
|
124
|
+
* structured analysis results, check out the documentation of the hosting
|
|
125
|
+
* heap analysis class and call the analysis-specific API to get results
|
|
126
|
+
* after calling this method.
|
|
100
127
|
* * **Example**:
|
|
101
128
|
* ```typescript
|
|
102
129
|
* const analysis = new ShapeUnboundGrowthAnalysis();
|
|
103
|
-
*
|
|
130
|
+
* // analysis console output is saved in result.analysisOutputFile
|
|
131
|
+
* const result = await analysis.analyzeSnapshotsInDirectory(snapshotDirectory);
|
|
132
|
+
* // query analysis-specific and structured results
|
|
104
133
|
* const shapes = analysis.getShapesWithUnboundGrowth();
|
|
105
134
|
* ```
|
|
135
|
+
* * Additionally, you can specify a working directory to where
|
|
136
|
+
* the intermediate, logging, and final output files will be dumped:
|
|
137
|
+
* ```typescript
|
|
138
|
+
* const analysis = new ShapeUnboundGrowthAnalysis();
|
|
139
|
+
* // analysis console output is saved in result.analysisOutputFile
|
|
140
|
+
* // which is inside the specified working directory
|
|
141
|
+
* const result = await analysis.analyzeSnapshotsInDirectory(snapshotDirectory, {
|
|
142
|
+
* // if the specified directory doesn't exist, memlab will create it
|
|
143
|
+
* workDir: '/tmp/your/work/dir',
|
|
144
|
+
* });
|
|
145
|
+
* ```
|
|
106
146
|
*/
|
|
107
|
-
analyzeSnapshotsInDirectory(directory) {
|
|
147
|
+
analyzeSnapshotsInDirectory(directory, options = {}) {
|
|
108
148
|
return __awaiter(this, void 0, void 0, function* () {
|
|
109
|
-
|
|
149
|
+
if (options.workDir) {
|
|
150
|
+
// set and init the new work dir
|
|
151
|
+
core_1.config.defaultFileManagerOption = options;
|
|
152
|
+
}
|
|
153
|
+
const analysisOutputFile = core_1.fileManager.initNewHeapAnalysisLogFile();
|
|
154
|
+
core_1.info.registerLogFile(analysisOutputFile);
|
|
155
|
+
yield this.process({
|
|
110
156
|
args: {
|
|
111
157
|
_: [],
|
|
112
158
|
snapshot: '<MUST_PROVIDE_SNAPSHOT_FILE>',
|
|
113
159
|
'snapshot-dir': directory,
|
|
114
160
|
},
|
|
115
161
|
});
|
|
162
|
+
core_1.info.unregisterLogFile(analysisOutputFile);
|
|
163
|
+
return { analysisOutputFile };
|
|
116
164
|
});
|
|
117
165
|
}
|
|
118
166
|
}
|
package/dist/PluginUtils.d.ts
CHANGED
|
@@ -25,6 +25,27 @@ export declare type HeapAnalysisOptions = {
|
|
|
25
25
|
/** @internal */
|
|
26
26
|
config?: MemLabConfig;
|
|
27
27
|
};
|
|
28
|
+
/**
|
|
29
|
+
* This is the input option for {@link analyzeSnapshotFromFile}
|
|
30
|
+
* and {@link analyzeSnapshotsInDirectory}.
|
|
31
|
+
*/
|
|
32
|
+
export declare type RunHeapAnalysisOptions = {
|
|
33
|
+
/**
|
|
34
|
+
* specify the working directory to where the intermediate, logging,
|
|
35
|
+
* and output files should be saved
|
|
36
|
+
*/
|
|
37
|
+
workDir?: string;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* This is the return type from calling {@link analyzeSnapshotFromFile}
|
|
41
|
+
* or {@link analyzeSnapshotsInDirectory}.
|
|
42
|
+
*/
|
|
43
|
+
export declare type AnalyzeSnapshotResult = {
|
|
44
|
+
/**
|
|
45
|
+
* file path of the console output of the heap analysis call
|
|
46
|
+
*/
|
|
47
|
+
analysisOutputFile: string;
|
|
48
|
+
};
|
|
28
49
|
declare type PrintNodeOption = {
|
|
29
50
|
indent?: string;
|
|
30
51
|
printReferences?: boolean;
|
package/dist/index.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ export declare function registerPackage(): Promise<void>;
|
|
|
12
12
|
export declare const getDominatorNodes: (ids: Set<number>, snapshot: import("@memlab/core").IHeapSnapshot) => Set<number>,
|
|
13
13
|
/** @deprecated */
|
|
14
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>;
|
|
15
|
-
export type { HeapAnalysisOptions } from './PluginUtils';
|
|
15
|
+
export type { AnalyzeSnapshotResult, HeapAnalysisOptions, RunHeapAnalysisOptions, } from './PluginUtils';
|
|
16
16
|
export { default as BaseAnalysis } from './BaseAnalysis';
|
|
17
17
|
export { default as DetachedDOMElementAnalysis } from './plugins/DetachedDOMElementAnalysis';
|
|
18
18
|
export { default as GlobalVariableAnalysis } from './plugins/GlobalVariableAnalysis/GlobalVariableAnalysis';
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* @format
|
|
8
8
|
* @oncall web_perf_infra
|
|
9
9
|
*/
|
|
10
|
-
import type { HeapAnalysisOptions } from '../PluginUtils';
|
|
10
|
+
import type { AnalyzeSnapshotResult, HeapAnalysisOptions } from '../PluginUtils';
|
|
11
11
|
import type { BaseOption } from '@memlab/core';
|
|
12
12
|
import BaseAnalysis from '../BaseAnalysis';
|
|
13
13
|
declare class CollectionUnboundGrowthAnalysis extends BaseAnalysis {
|
|
@@ -17,7 +17,7 @@ declare class CollectionUnboundGrowthAnalysis extends BaseAnalysis {
|
|
|
17
17
|
/** @internal */
|
|
18
18
|
getOptions(): BaseOption[];
|
|
19
19
|
/** @internal */
|
|
20
|
-
analyzeSnapshotFromFile(file: string): Promise<
|
|
20
|
+
analyzeSnapshotFromFile(file: string): Promise<AnalyzeSnapshotResult>;
|
|
21
21
|
/** @internal */
|
|
22
22
|
process(options: HeapAnalysisOptions): Promise<void>;
|
|
23
23
|
private checkUnboundCollection;
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* @format
|
|
8
8
|
* @oncall web_perf_infra
|
|
9
9
|
*/
|
|
10
|
-
import type { HeapAnalysisOptions } from '../PluginUtils';
|
|
10
|
+
import type { AnalyzeSnapshotResult, HeapAnalysisOptions } from '../PluginUtils';
|
|
11
11
|
import { BaseOption } from '@memlab/core';
|
|
12
12
|
import BaseAnalysis from '../BaseAnalysis';
|
|
13
13
|
export default class CollectionsHoldingStaleAnalysis extends BaseAnalysis {
|
|
@@ -17,7 +17,7 @@ export default class CollectionsHoldingStaleAnalysis extends BaseAnalysis {
|
|
|
17
17
|
/** @internal */
|
|
18
18
|
getOptions(): BaseOption[];
|
|
19
19
|
/** @internal */
|
|
20
|
-
analyzeSnapshotsInDirectory(directory: string): Promise<
|
|
20
|
+
analyzeSnapshotsInDirectory(directory: string): Promise<AnalyzeSnapshotResult>;
|
|
21
21
|
private staleCollectionMapper;
|
|
22
22
|
/** @internal */
|
|
23
23
|
process(options: HeapAnalysisOptions): Promise<void>;
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* @format
|
|
8
8
|
* @oncall web_perf_infra
|
|
9
9
|
*/
|
|
10
|
-
import type { HeapAnalysisOptions } from '../PluginUtils';
|
|
10
|
+
import type { AnalyzeSnapshotResult, HeapAnalysisOptions } from '../PluginUtils';
|
|
11
11
|
import type { IHeapNode } from '@memlab/core';
|
|
12
12
|
import { BaseOption } from '@memlab/core';
|
|
13
13
|
import BaseAnalysis from '../BaseAnalysis';
|
|
@@ -18,7 +18,7 @@ export default class DetachedDOMElementAnalysis extends BaseAnalysis {
|
|
|
18
18
|
/** @internal */
|
|
19
19
|
getOptions(): BaseOption[];
|
|
20
20
|
/** @internal */
|
|
21
|
-
analyzeSnapshotsInDirectory(directory: string): Promise<
|
|
21
|
+
analyzeSnapshotsInDirectory(directory: string): Promise<AnalyzeSnapshotResult>;
|
|
22
22
|
private detachedElements;
|
|
23
23
|
getDetachedElements(): IHeapNode[];
|
|
24
24
|
/** @internal */
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* @format
|
|
8
8
|
* @oncall web_perf_infra
|
|
9
9
|
*/
|
|
10
|
-
import type { HeapAnalysisOptions } from '../../PluginUtils';
|
|
10
|
+
import type { AnalyzeSnapshotResult, HeapAnalysisOptions } from '../../PluginUtils';
|
|
11
11
|
import { BaseOption } from '@memlab/core';
|
|
12
12
|
import BaseAnalysis from '../../BaseAnalysis';
|
|
13
13
|
declare class GlobalVariableAnalysis extends BaseAnalysis {
|
|
@@ -19,7 +19,7 @@ declare class GlobalVariableAnalysis extends BaseAnalysis {
|
|
|
19
19
|
/** @internal */
|
|
20
20
|
process(options: HeapAnalysisOptions): Promise<void>;
|
|
21
21
|
/** @internal */
|
|
22
|
-
analyzeSnapshotsInDirectory(directory: string): Promise<
|
|
22
|
+
analyzeSnapshotsInDirectory(directory: string): Promise<AnalyzeSnapshotResult>;
|
|
23
23
|
private shouldFilterOutEdge;
|
|
24
24
|
/** @internal */
|
|
25
25
|
private getGlobalVariables;
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* @format
|
|
8
8
|
* @oncall web_perf_infra
|
|
9
9
|
*/
|
|
10
|
-
import type { HeapAnalysisOptions } from '../PluginUtils';
|
|
10
|
+
import type { AnalyzeSnapshotResult, HeapAnalysisOptions } from '../PluginUtils';
|
|
11
11
|
import { BaseOption } from '@memlab/core';
|
|
12
12
|
import BaseAnalysis from '../BaseAnalysis';
|
|
13
13
|
declare class GlobalVariableAnalysis extends BaseAnalysis {
|
|
@@ -19,7 +19,7 @@ declare class GlobalVariableAnalysis extends BaseAnalysis {
|
|
|
19
19
|
/** @internal */
|
|
20
20
|
process(options: HeapAnalysisOptions): Promise<void>;
|
|
21
21
|
/** @internal */
|
|
22
|
-
analyzeSnapshotsInDirectory(directory: string): Promise<
|
|
22
|
+
analyzeSnapshotsInDirectory(directory: string): Promise<AnalyzeSnapshotResult>;
|
|
23
23
|
/** @internal */
|
|
24
24
|
private getObjectProperties;
|
|
25
25
|
/** @internal */
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* @format
|
|
8
8
|
* @oncall web_perf_infra
|
|
9
9
|
*/
|
|
10
|
-
import type { HeapAnalysisOptions } from '../PluginUtils';
|
|
10
|
+
import type { AnalyzeSnapshotResult, HeapAnalysisOptions } from '../PluginUtils';
|
|
11
11
|
import { BaseOption } from '@memlab/core';
|
|
12
12
|
import BaseAnalysis from '../BaseAnalysis';
|
|
13
13
|
declare class ObjectFanoutAnalysis extends BaseAnalysis {
|
|
@@ -17,7 +17,7 @@ declare class ObjectFanoutAnalysis extends BaseAnalysis {
|
|
|
17
17
|
/** @internal */
|
|
18
18
|
getOptions(): BaseOption[];
|
|
19
19
|
/** @internal */
|
|
20
|
-
analyzeSnapshotsInDirectory(directory: string): Promise<
|
|
20
|
+
analyzeSnapshotsInDirectory(directory: string): Promise<AnalyzeSnapshotResult>;
|
|
21
21
|
/** @internal */
|
|
22
22
|
process(options: HeapAnalysisOptions): Promise<void>;
|
|
23
23
|
private getObjectsWithHighFanout;
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* @format
|
|
8
8
|
* @oncall web_perf_infra
|
|
9
9
|
*/
|
|
10
|
-
import type { HeapAnalysisOptions } from '../PluginUtils';
|
|
10
|
+
import type { AnalyzeSnapshotResult, HeapAnalysisOptions } from '../PluginUtils';
|
|
11
11
|
import { BaseOption } from '@memlab/core';
|
|
12
12
|
import BaseAnalysis from '../BaseAnalysis';
|
|
13
13
|
/**
|
|
@@ -44,7 +44,7 @@ declare class ObjectShallowAnalysis extends BaseAnalysis {
|
|
|
44
44
|
/** @internal */
|
|
45
45
|
getOptions(): BaseOption[];
|
|
46
46
|
/** @internal */
|
|
47
|
-
analyzeSnapshotsInDirectory(directory: string): Promise<
|
|
47
|
+
analyzeSnapshotsInDirectory(directory: string): Promise<AnalyzeSnapshotResult>;
|
|
48
48
|
/** @internal */
|
|
49
49
|
process(options: HeapAnalysisOptions): Promise<void>;
|
|
50
50
|
/**
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
* @format
|
|
8
8
|
* @oncall web_perf_infra
|
|
9
9
|
*/
|
|
10
|
-
import type { HeapAnalysisOptions } from '../PluginUtils';
|
|
11
|
-
import { BaseOption } from '@memlab/core';
|
|
10
|
+
import type { AnalyzeSnapshotResult, HeapAnalysisOptions } from '../PluginUtils';
|
|
11
|
+
import type { BaseOption } from '@memlab/core';
|
|
12
12
|
import BaseAnalysis from '../BaseAnalysis';
|
|
13
13
|
declare class ObjectShapeAnalysis extends BaseAnalysis {
|
|
14
14
|
getCommandName(): string;
|
|
@@ -17,9 +17,19 @@ declare class ObjectShapeAnalysis extends BaseAnalysis {
|
|
|
17
17
|
/** @internal */
|
|
18
18
|
getOptions(): BaseOption[];
|
|
19
19
|
/** @internal */
|
|
20
|
-
analyzeSnapshotsInDirectory(directory: string): Promise<
|
|
20
|
+
analyzeSnapshotsInDirectory(directory: string): Promise<AnalyzeSnapshotResult>;
|
|
21
21
|
/** @internal */
|
|
22
22
|
process(options: HeapAnalysisOptions): Promise<void>;
|
|
23
|
+
/** @internal */
|
|
24
|
+
breakDownMemoryByShapes(options?: {
|
|
25
|
+
file?: string;
|
|
26
|
+
}): Promise<void>;
|
|
27
|
+
/** @internal */
|
|
28
|
+
private breakDownSnapshotByShapes;
|
|
29
|
+
/** @internal */
|
|
30
|
+
private breakDownByReferrers;
|
|
31
|
+
/** @internal */
|
|
32
|
+
private isTrivialEdgeForBreakDown;
|
|
23
33
|
}
|
|
24
34
|
export default ObjectShapeAnalysis;
|
|
25
35
|
//# sourceMappingURL=ObjectShapeAnalysis.d.ts.map
|
|
@@ -21,6 +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
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
24
25
|
const core_1 = require("@memlab/core");
|
|
25
26
|
const BaseAnalysis_1 = __importDefault(require("../BaseAnalysis"));
|
|
26
27
|
const PluginUtils_1 = __importDefault(require("../PluginUtils"));
|
|
@@ -49,8 +50,132 @@ class ObjectShapeAnalysis extends BaseAnalysis_1.default {
|
|
|
49
50
|
process(options) {
|
|
50
51
|
return __awaiter(this, void 0, void 0, function* () {
|
|
51
52
|
const snapshotPath = PluginUtils_1.default.getSnapshotFileForAnalysis(options);
|
|
52
|
-
yield
|
|
53
|
+
yield this.breakDownMemoryByShapes({ file: snapshotPath });
|
|
53
54
|
});
|
|
54
55
|
}
|
|
56
|
+
/** @internal */
|
|
57
|
+
breakDownMemoryByShapes(options = {}) {
|
|
58
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
59
|
+
const opt = { buildNodeIdIndex: true, verbose: true };
|
|
60
|
+
const file = options.file ||
|
|
61
|
+
core_1.utils.getSnapshotFilePathWithTabType(/.*/) ||
|
|
62
|
+
'<EMPTY_FILE_PATH>';
|
|
63
|
+
const snapshot = yield core_1.utils.getSnapshotFromFile(file, opt);
|
|
64
|
+
core_1.analysis.preparePathFinder(snapshot);
|
|
65
|
+
const heapInfo = core_1.analysis.getOverallHeapInfo(snapshot, { force: true });
|
|
66
|
+
if (heapInfo) {
|
|
67
|
+
core_1.analysis.printHeapInfo(heapInfo);
|
|
68
|
+
}
|
|
69
|
+
this.breakDownSnapshotByShapes(snapshot);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
/** @internal */
|
|
73
|
+
breakDownSnapshotByShapes(snapshot) {
|
|
74
|
+
core_1.info.overwrite('Breaking down memory by shapes...');
|
|
75
|
+
const breakdown = Object.create(null);
|
|
76
|
+
const population = Object.create(null);
|
|
77
|
+
// group objects based on their shapes
|
|
78
|
+
snapshot.nodes.forEach((node) => {
|
|
79
|
+
if ((node.type !== 'object' && !core_1.utils.isStringNode(node)) ||
|
|
80
|
+
core_1.config.nodeIgnoreSetInShape.has(node.name)) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const key = core_1.serializer.summarizeNodeShape(node);
|
|
84
|
+
breakdown[key] = breakdown[key] || new Set();
|
|
85
|
+
breakdown[key].add(node.id);
|
|
86
|
+
if (population[key] === undefined) {
|
|
87
|
+
population[key] = { examples: [], n: 0 };
|
|
88
|
+
}
|
|
89
|
+
++population[key].n;
|
|
90
|
+
// retain the top 5 examples
|
|
91
|
+
const examples = population[key].examples;
|
|
92
|
+
examples.push(node);
|
|
93
|
+
examples.sort((n1, n2) => n2.retainedSize - n1.retainedSize);
|
|
94
|
+
if (examples.length > 5) {
|
|
95
|
+
examples.pop();
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
// calculate and sort based on retained sizes
|
|
99
|
+
const ret = [];
|
|
100
|
+
for (const key in breakdown) {
|
|
101
|
+
const size = core_1.utils.aggregateDominatorMetrics(breakdown[key], snapshot, () => true, core_1.utils.getRetainedSize);
|
|
102
|
+
ret.push({ key, retainedSize: size });
|
|
103
|
+
}
|
|
104
|
+
ret.sort((o1, o2) => o2.retainedSize - o1.retainedSize);
|
|
105
|
+
core_1.info.topLevel('Object shapes with top retained sizes:');
|
|
106
|
+
core_1.info.lowLevel(' (Use `memlab trace --node-id=@ID` to get trace)\n');
|
|
107
|
+
const topList = ret.slice(0, 40);
|
|
108
|
+
// print settings
|
|
109
|
+
const opt = { color: true, compact: true };
|
|
110
|
+
const dot = chalk_1.default.grey('· ');
|
|
111
|
+
const colon = chalk_1.default.grey(': ');
|
|
112
|
+
// print the shapes with the biggest retained size
|
|
113
|
+
for (const o of topList) {
|
|
114
|
+
const referrerInfo = this.breakDownByReferrers(breakdown[o.key], snapshot);
|
|
115
|
+
const { examples, n } = population[o.key];
|
|
116
|
+
const shapeStr = core_1.serializer.summarizeNodeShape(examples[0], opt);
|
|
117
|
+
const bytes = core_1.utils.getReadableBytes(o.retainedSize);
|
|
118
|
+
const examplesStr = examples
|
|
119
|
+
.map(e => `@${e.id} [${core_1.utils.getReadableBytes(e.retainedSize)}]`)
|
|
120
|
+
.join(' | ');
|
|
121
|
+
const meta = chalk_1.default.grey(` (N: ${n}, Examples: ${examplesStr})`);
|
|
122
|
+
core_1.info.topLevel(`${dot}${shapeStr}${colon}${bytes}${meta}`);
|
|
123
|
+
core_1.info.lowLevel(referrerInfo + '\n');
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/** @internal */
|
|
127
|
+
breakDownByReferrers(ids, snapshot) {
|
|
128
|
+
const edgeNames = Object.create(null);
|
|
129
|
+
for (const id of ids) {
|
|
130
|
+
const node = snapshot.getNodeById(id);
|
|
131
|
+
for (const edge of (node === null || node === void 0 ? void 0 : node.referrers) || []) {
|
|
132
|
+
const source = edge.fromNode;
|
|
133
|
+
if (!core_1.utils.isMeaningfulEdge(edge) ||
|
|
134
|
+
this.isTrivialEdgeForBreakDown(edge)) {
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
const sourceName = core_1.serializer.summarizeNodeName(source, {
|
|
138
|
+
color: false,
|
|
139
|
+
});
|
|
140
|
+
const edgeName = core_1.serializer.summarizeEdgeName(edge, {
|
|
141
|
+
color: false,
|
|
142
|
+
abstract: true,
|
|
143
|
+
});
|
|
144
|
+
const edgeKey = `[${sourceName}] --${edgeName}--> `;
|
|
145
|
+
edgeNames[edgeKey] = edgeNames[edgeKey] || {
|
|
146
|
+
numberOfEdgesToNode: 0,
|
|
147
|
+
source,
|
|
148
|
+
edge,
|
|
149
|
+
};
|
|
150
|
+
++edgeNames[edgeKey].numberOfEdgesToNode;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
const referrerInfo = Object.entries(edgeNames)
|
|
154
|
+
.sort((i1, i2) => i2[1].numberOfEdgesToNode - i1[1].numberOfEdgesToNode)
|
|
155
|
+
.slice(0, 4)
|
|
156
|
+
.map(i => {
|
|
157
|
+
const meta = i[1];
|
|
158
|
+
const source = core_1.serializer.summarizeNodeName(meta.source, {
|
|
159
|
+
color: true,
|
|
160
|
+
});
|
|
161
|
+
const edgeName = core_1.serializer.summarizeEdgeName(meta.edge, {
|
|
162
|
+
color: true,
|
|
163
|
+
abstract: true,
|
|
164
|
+
});
|
|
165
|
+
const edgeSummary = `${source} --${edgeName}-->`;
|
|
166
|
+
return ` · ${edgeSummary}: ${meta.numberOfEdgesToNode}`;
|
|
167
|
+
})
|
|
168
|
+
.join('\n');
|
|
169
|
+
return referrerInfo;
|
|
170
|
+
}
|
|
171
|
+
/** @internal */
|
|
172
|
+
isTrivialEdgeForBreakDown(edge) {
|
|
173
|
+
const source = edge.fromNode;
|
|
174
|
+
return (source.type === 'array' ||
|
|
175
|
+
source.name === '(object elements)' ||
|
|
176
|
+
source.name === 'system' ||
|
|
177
|
+
edge.name_or_index === '__proto__' ||
|
|
178
|
+
edge.name_or_index === 'prototype');
|
|
179
|
+
}
|
|
55
180
|
}
|
|
56
181
|
exports.default = ObjectShapeAnalysis;
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* @format
|
|
8
8
|
* @oncall web_perf_infra
|
|
9
9
|
*/
|
|
10
|
-
import type { HeapAnalysisOptions } from '../PluginUtils';
|
|
10
|
+
import type { AnalyzeSnapshotResult, HeapAnalysisOptions } from '../PluginUtils';
|
|
11
11
|
import { BaseOption } from '@memlab/core';
|
|
12
12
|
import BaseAnalysis from '../BaseAnalysis';
|
|
13
13
|
declare class ObjectSizeRankAnalysis extends BaseAnalysis {
|
|
@@ -17,7 +17,7 @@ declare class ObjectSizeRankAnalysis extends BaseAnalysis {
|
|
|
17
17
|
/** @internal */
|
|
18
18
|
getOptions(): BaseOption[];
|
|
19
19
|
/** @internal */
|
|
20
|
-
analyzeSnapshotsInDirectory(directory: string): Promise<
|
|
20
|
+
analyzeSnapshotsInDirectory(directory: string): Promise<AnalyzeSnapshotResult>;
|
|
21
21
|
/** @internal */
|
|
22
22
|
process(options: HeapAnalysisOptions): Promise<void>;
|
|
23
23
|
}
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
* @format
|
|
8
8
|
* @oncall web_perf_infra
|
|
9
9
|
*/
|
|
10
|
-
import type {
|
|
11
|
-
import {
|
|
10
|
+
import type { BaseOption } from '@memlab/core';
|
|
11
|
+
import type { AnalyzeSnapshotResult, HeapAnalysisOptions } from '../PluginUtils';
|
|
12
12
|
import BaseAnalysis from '../BaseAnalysis';
|
|
13
13
|
declare class ObjectUnboundGrowthAnalysis extends BaseAnalysis {
|
|
14
14
|
getCommandName(): string;
|
|
@@ -17,9 +17,12 @@ declare class ObjectUnboundGrowthAnalysis extends BaseAnalysis {
|
|
|
17
17
|
/** @internal */
|
|
18
18
|
getOptions(): BaseOption[];
|
|
19
19
|
/** @internal */
|
|
20
|
-
analyzeSnapshotFromFile(file: string): Promise<
|
|
20
|
+
analyzeSnapshotFromFile(file: string): Promise<AnalyzeSnapshotResult>;
|
|
21
21
|
/** @internal */
|
|
22
22
|
process(options: HeapAnalysisOptions): Promise<void>;
|
|
23
|
+
private checkUnbound;
|
|
24
|
+
private detectUnboundGrowth;
|
|
25
|
+
private calculateRetainedSizes;
|
|
23
26
|
}
|
|
24
27
|
export default ObjectUnboundGrowthAnalysis;
|
|
25
28
|
//# sourceMappingURL=ObjectUnboundGrowthAnalysis.d.ts.map
|
|
@@ -21,6 +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
|
+
const fs_1 = __importDefault(require("fs"));
|
|
24
25
|
const core_1 = require("@memlab/core");
|
|
25
26
|
const BaseAnalysis_1 = __importDefault(require("../BaseAnalysis"));
|
|
26
27
|
const HeapAnalysisSnapshotDirectoryOption_1 = __importDefault(require("../options/HeapAnalysisSnapshotDirectoryOption"));
|
|
@@ -52,8 +53,148 @@ class ObjectUnboundGrowthAnalysis extends BaseAnalysis_1.default {
|
|
|
52
53
|
const snapshotDir = PluginUtils_1.default.getSnapshotDirForAnalysis(options);
|
|
53
54
|
const opt = snapshotDir ? { minSnapshots: 2, snapshotDir } : {};
|
|
54
55
|
core_1.config.chaseWeakMapEdge = false;
|
|
55
|
-
yield
|
|
56
|
+
yield this.checkUnbound(opt);
|
|
56
57
|
});
|
|
57
58
|
}
|
|
59
|
+
checkUnbound(options = {}) {
|
|
60
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
61
|
+
core_1.analysis.visualizeMemoryUsage(options);
|
|
62
|
+
core_1.utils.checkSnapshots(options);
|
|
63
|
+
yield this.detectUnboundGrowth(options);
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
// find any objects that keeps growing
|
|
67
|
+
detectUnboundGrowth(options = {}) {
|
|
68
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
69
|
+
const nodeInfo = Object.create(null);
|
|
70
|
+
let hasCheckedFirstSnapshot = false;
|
|
71
|
+
let snapshot = null;
|
|
72
|
+
const isValidNode = (node) => node.type === 'object' ||
|
|
73
|
+
node.type === 'closure' ||
|
|
74
|
+
node.type === 'regexp';
|
|
75
|
+
const initNodeInfo = (node) => {
|
|
76
|
+
if (!isValidNode(node)) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
const n = node.retainedSize;
|
|
80
|
+
nodeInfo[node.id] = {
|
|
81
|
+
type: node.type,
|
|
82
|
+
name: node.name,
|
|
83
|
+
min: n,
|
|
84
|
+
max: n,
|
|
85
|
+
history: [n],
|
|
86
|
+
node,
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
const updateNodeInfo = (node) => {
|
|
90
|
+
const item = nodeInfo[node.id];
|
|
91
|
+
if (!item) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
if (node.name !== item.name || node.type !== item.type) {
|
|
95
|
+
nodeInfo[node.id] = null;
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const n = node.retainedSize;
|
|
99
|
+
// only monotonic increase?
|
|
100
|
+
if (core_1.config.monotonicUnboundGrowthOnly && n < item.max) {
|
|
101
|
+
nodeInfo[node.id] = null;
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
item.history.push(n);
|
|
105
|
+
item.max = Math.max(item.max, n);
|
|
106
|
+
item.min = Math.min(item.min, n);
|
|
107
|
+
};
|
|
108
|
+
// summarize the heap objects info in current heap snapshot
|
|
109
|
+
// this is mainly used for better understanding of the % of
|
|
110
|
+
// objects released and allocated over time
|
|
111
|
+
const maybeSummarizeNodeInfo = () => {
|
|
112
|
+
if (!core_1.config.verbose) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
let n = 0;
|
|
116
|
+
for (const k in nodeInfo) {
|
|
117
|
+
if (nodeInfo[k]) {
|
|
118
|
+
++n;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
core_1.info.lowLevel(`Objects tracked: ${n}`);
|
|
122
|
+
};
|
|
123
|
+
core_1.info.overwrite('Checking unbounded objects...');
|
|
124
|
+
const snapshotFiles = options.snapshotDir
|
|
125
|
+
? // load snapshots from a directory
|
|
126
|
+
core_1.utils.getSnapshotFilesInDir(options.snapshotDir)
|
|
127
|
+
: // load snapshots based on the visit sequence meta data
|
|
128
|
+
core_1.utils.getSnapshotFilesFromTabsOrder();
|
|
129
|
+
for (const file of snapshotFiles) {
|
|
130
|
+
// force GC before loading each snapshot
|
|
131
|
+
if (global.gc) {
|
|
132
|
+
global.gc();
|
|
133
|
+
}
|
|
134
|
+
// load and preprocess heap snapshot
|
|
135
|
+
const opt = { buildNodeIdIndex: true, verbose: true };
|
|
136
|
+
snapshot = yield core_1.utils.getSnapshotFromFile(file, opt);
|
|
137
|
+
this.calculateRetainedSizes(snapshot);
|
|
138
|
+
// keep track of heap objects
|
|
139
|
+
if (!hasCheckedFirstSnapshot) {
|
|
140
|
+
// record Ids in the snapshot
|
|
141
|
+
snapshot.nodes.forEach(initNodeInfo);
|
|
142
|
+
hasCheckedFirstSnapshot = true;
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
snapshot.nodes.forEach(updateNodeInfo);
|
|
146
|
+
maybeSummarizeNodeInfo();
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
// exit if no heap snapshot found
|
|
150
|
+
if (!hasCheckedFirstSnapshot) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
// post process and print the unbounded objects
|
|
154
|
+
const idsInLastSnapshot = new Set();
|
|
155
|
+
snapshot === null || snapshot === void 0 ? void 0 : snapshot.nodes.forEach(node => {
|
|
156
|
+
idsInLastSnapshot.add(node.id);
|
|
157
|
+
});
|
|
158
|
+
let ids = [];
|
|
159
|
+
for (const key in nodeInfo) {
|
|
160
|
+
const id = parseInt(key, 10);
|
|
161
|
+
const item = nodeInfo[id];
|
|
162
|
+
if (!item) {
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
if (!idsInLastSnapshot.has(id)) {
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
if (item.min === item.max) {
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
// filter out non-significant leaks
|
|
172
|
+
if (item.history[item.history.length - 1] < core_1.config.unboundSizeThreshold) {
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
ids.push(Object.assign({ id }, item));
|
|
176
|
+
}
|
|
177
|
+
if (ids.length === 0) {
|
|
178
|
+
core_1.info.midLevel('No increasing objects found.');
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
ids = ids
|
|
182
|
+
.sort((o1, o2) => o2.history[o2.history.length - 1] - o1.history[o1.history.length - 1])
|
|
183
|
+
.slice(0, 20);
|
|
184
|
+
// print on terminal
|
|
185
|
+
const str = core_1.serializer.summarizeUnboundedObjects(ids, { color: true });
|
|
186
|
+
core_1.info.topLevel('Top growing objects in sizes:');
|
|
187
|
+
core_1.info.lowLevel(' (Use `memlab trace --node-id=@ID` to get trace)');
|
|
188
|
+
core_1.info.topLevel('\n' + str);
|
|
189
|
+
// save results to file
|
|
190
|
+
const csv = core_1.serializer.summarizeUnboundedObjectsToCSV(ids);
|
|
191
|
+
fs_1.default.writeFileSync(core_1.config.unboundObjectCSV, csv, 'UTF-8');
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
calculateRetainedSizes(snapshot) {
|
|
195
|
+
const finder = new core_1.TraceFinder();
|
|
196
|
+
// dominator and retained size
|
|
197
|
+
finder.calculateAllNodesRetainedSizes(snapshot);
|
|
198
|
+
}
|
|
58
199
|
}
|
|
59
200
|
exports.default = ObjectUnboundGrowthAnalysis;
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* @format
|
|
8
8
|
* @oncall web_perf_infra
|
|
9
9
|
*/
|
|
10
|
-
import type { HeapAnalysisOptions } from '../PluginUtils';
|
|
10
|
+
import type { AnalyzeSnapshotResult, HeapAnalysisOptions } from '../PluginUtils';
|
|
11
11
|
import { BaseOption } from '@memlab/core';
|
|
12
12
|
import BaseAnalysis from '../BaseAnalysis';
|
|
13
13
|
declare type ShapeSummary = {
|
|
@@ -25,7 +25,7 @@ export default class ShapeUnboundGrowthAnalysis extends BaseAnalysis {
|
|
|
25
25
|
/** @internal */
|
|
26
26
|
getOptions(): BaseOption[];
|
|
27
27
|
/** @internal */
|
|
28
|
-
analyzeSnapshotFromFile(file: string): Promise<
|
|
28
|
+
analyzeSnapshotFromFile(file: string): Promise<AnalyzeSnapshotResult>;
|
|
29
29
|
getShapesWithUnboundGrowth(): ShapeSummary[];
|
|
30
30
|
/** @internal */
|
|
31
31
|
process(options: HeapAnalysisOptions): Promise<void>;
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* @format
|
|
8
8
|
* @oncall web_perf_infra
|
|
9
9
|
*/
|
|
10
|
-
import type { HeapAnalysisOptions } from '../PluginUtils';
|
|
10
|
+
import type { AnalyzeSnapshotResult, HeapAnalysisOptions } from '../PluginUtils';
|
|
11
11
|
import { BaseOption } from '@memlab/core';
|
|
12
12
|
import BaseAnalysis from '../BaseAnalysis';
|
|
13
13
|
/**
|
|
@@ -58,7 +58,7 @@ export default class StringAnalysis extends BaseAnalysis {
|
|
|
58
58
|
/** @internal */
|
|
59
59
|
getOptions(): BaseOption[];
|
|
60
60
|
/** @internal */
|
|
61
|
-
analyzeSnapshotsInDirectory(directory: string): Promise<
|
|
61
|
+
analyzeSnapshotsInDirectory(directory: string): Promise<AnalyzeSnapshotResult>;
|
|
62
62
|
private static shouldIgnoreNode;
|
|
63
63
|
/** @internal */
|
|
64
64
|
process(options: HeapAnalysisOptions): Promise<void>;
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* @format
|
|
8
8
|
* @oncall web_perf_infra
|
|
9
9
|
*/
|
|
10
|
-
import type { HeapAnalysisOptions } from '../PluginUtils';
|
|
10
|
+
import type { AnalyzeSnapshotResult, HeapAnalysisOptions } from '../PluginUtils';
|
|
11
11
|
import { BaseOption } from '@memlab/core';
|
|
12
12
|
import BaseAnalysis from '../BaseAnalysis';
|
|
13
13
|
export default class UnmountedFiberNodeAnalysis extends BaseAnalysis {
|
|
@@ -17,7 +17,7 @@ export default class UnmountedFiberNodeAnalysis extends BaseAnalysis {
|
|
|
17
17
|
/** @internal */
|
|
18
18
|
getOptions(): BaseOption[];
|
|
19
19
|
/** @internal */
|
|
20
|
-
analyzeSnapshotsInDirectory(directory: string): Promise<
|
|
20
|
+
analyzeSnapshotsInDirectory(directory: string): Promise<AnalyzeSnapshotResult>;
|
|
21
21
|
/** @internal */
|
|
22
22
|
process(options: HeapAnalysisOptions): Promise<void>;
|
|
23
23
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memlab/heap-analysis",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.16",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "heap analysis plugins for memlab",
|
|
6
6
|
"author": "Liang Gong <lgong@fb.com>",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"scripts": {
|
|
51
51
|
"build-pkg": "tsc",
|
|
52
52
|
"test-pkg": "jest .",
|
|
53
|
-
"publish-patch": "npm
|
|
53
|
+
"publish-patch": "npm publish",
|
|
54
54
|
"clean-pkg": "rm -rf ./dist && rm -rf ./node_modules && rm -f ./tsconfig.tsbuildinfo"
|
|
55
55
|
},
|
|
56
56
|
"bugs": {
|