@memlab/core 1.1.14 → 1.1.17
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/index.d.ts +4 -0
- package/dist/index.js +6 -1
- package/dist/lib/Config.d.ts +6 -0
- package/dist/lib/Config.js +10 -1
- package/dist/lib/Console.d.ts +3 -0
- package/dist/lib/Console.js +81 -28
- package/dist/lib/FileManager.d.ts +4 -0
- package/dist/lib/FileManager.js +27 -0
- package/dist/lib/HeapAnalyzer.d.ts +5 -14
- package/dist/lib/HeapAnalyzer.js +9 -285
- package/dist/lib/Serializer.js +1 -1
- package/dist/lib/Types.d.ts +74 -7
- package/dist/lib/Utils.d.ts +7 -1
- package/dist/lib/Utils.js +58 -4
- package/dist/lib/heap-data/HeapNode.js +3 -4
- package/dist/lib/heap-data/HeapSnapshot.js +2 -2
- package/dist/trace-cluster/ClusterUtils.d.ts +15 -1
- package/dist/trace-cluster/ClusterUtils.js +42 -0
- package/dist/trace-cluster/MultiIterationSeqClustering.d.ts +21 -0
- package/dist/trace-cluster/MultiIterationSeqClustering.js +112 -0
- package/dist/trace-cluster/TraceBucket.js +3 -3
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -50,5 +50,9 @@ export * from './lib/PackageInfoLoader';
|
|
|
50
50
|
/** @internal */
|
|
51
51
|
export { default as SequentialClustering } from './trace-cluster/SequentialClustering';
|
|
52
52
|
/** @internal */
|
|
53
|
+
export { default as MultiIterationSeqClustering } from './trace-cluster/MultiIterationSeqClustering';
|
|
54
|
+
/** @internal */
|
|
53
55
|
export { default as TraceFinder } from './paths/TraceFinder';
|
|
56
|
+
/** @internal */
|
|
57
|
+
export * from './trace-cluster/ClusterUtils';
|
|
54
58
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -35,7 +35,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
35
35
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
36
36
|
};
|
|
37
37
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
|
-
exports.TraceFinder = exports.SequentialClustering = exports.EvaluationMetric = exports.NormalizedTrace = exports.leakClusterLogger = exports.ProcessManager = exports.modes = exports.constant = exports.analysis = exports.browserInfo = exports.serializer = exports.fileManager = exports.utils = exports.BaseOption = exports.info = exports.config = exports.registerPackage = void 0;
|
|
38
|
+
exports.TraceFinder = exports.MultiIterationSeqClustering = exports.SequentialClustering = exports.EvaluationMetric = exports.NormalizedTrace = exports.leakClusterLogger = exports.ProcessManager = exports.modes = exports.constant = exports.analysis = exports.browserInfo = exports.serializer = exports.fileManager = exports.utils = exports.BaseOption = exports.info = exports.config = exports.registerPackage = void 0;
|
|
39
39
|
const path_1 = __importDefault(require("path"));
|
|
40
40
|
const PackageInfoLoader_1 = require("./lib/PackageInfoLoader");
|
|
41
41
|
/** @internal */
|
|
@@ -101,5 +101,10 @@ __exportStar(require("./lib/PackageInfoLoader"), exports);
|
|
|
101
101
|
var SequentialClustering_1 = require("./trace-cluster/SequentialClustering");
|
|
102
102
|
Object.defineProperty(exports, "SequentialClustering", { enumerable: true, get: function () { return __importDefault(SequentialClustering_1).default; } });
|
|
103
103
|
/** @internal */
|
|
104
|
+
var MultiIterationSeqClustering_1 = require("./trace-cluster/MultiIterationSeqClustering");
|
|
105
|
+
Object.defineProperty(exports, "MultiIterationSeqClustering", { enumerable: true, get: function () { return __importDefault(MultiIterationSeqClustering_1).default; } });
|
|
106
|
+
/** @internal */
|
|
104
107
|
var TraceFinder_1 = require("./paths/TraceFinder");
|
|
105
108
|
Object.defineProperty(exports, "TraceFinder", { enumerable: true, get: function () { return __importDefault(TraceFinder_1).default; } });
|
|
109
|
+
/** @internal */
|
|
110
|
+
__exportStar(require("./trace-cluster/ClusterUtils"), exports);
|
package/dist/lib/Config.d.ts
CHANGED
|
@@ -71,6 +71,7 @@ export declare class MemLabConfig {
|
|
|
71
71
|
userDataDir: string;
|
|
72
72
|
curDataDir: string;
|
|
73
73
|
webSourceDir: string;
|
|
74
|
+
debugDataDir: string;
|
|
74
75
|
runMetaFile: string;
|
|
75
76
|
snapshotSequenceFile: string;
|
|
76
77
|
exploreResultFile: string;
|
|
@@ -90,6 +91,7 @@ export declare class MemLabConfig {
|
|
|
90
91
|
traceClusterOutDir: string;
|
|
91
92
|
traceJsonOutDir: string;
|
|
92
93
|
metricsOutDir: string;
|
|
94
|
+
heapAnalysisLogDir: string;
|
|
93
95
|
reportScreenshotFile: string;
|
|
94
96
|
newUniqueClusterDir: string;
|
|
95
97
|
staleUniqueClusterDir: string;
|
|
@@ -188,9 +190,13 @@ export declare class MemLabConfig {
|
|
|
188
190
|
mlClusteringLinkageMaxDistance: number;
|
|
189
191
|
mlMaxDF: number;
|
|
190
192
|
isSequentialClustering: boolean;
|
|
193
|
+
isMultiIterationSeqClustering: boolean;
|
|
191
194
|
seqClusteringSplitCount: number;
|
|
195
|
+
multiIterSeqClusteringIteration: number;
|
|
196
|
+
multiIterSeqClusteringSampleSize: number;
|
|
192
197
|
seqClusteringIsRandomChunks: boolean;
|
|
193
198
|
instrumentJS: boolean;
|
|
199
|
+
interceptScript: boolean;
|
|
194
200
|
constructor(options?: ConfigOption);
|
|
195
201
|
private initInternalConfigs;
|
|
196
202
|
private init;
|
package/dist/lib/Config.js
CHANGED
|
@@ -116,7 +116,9 @@ class MemLabConfig {
|
|
|
116
116
|
this.snapshotHasDetachedness = false;
|
|
117
117
|
// by default running in regular mode
|
|
118
118
|
this.runningMode = RunningModes_1.default.get('regular', this);
|
|
119
|
-
// intercept and
|
|
119
|
+
// intercept and log JavaScript Code in browser
|
|
120
|
+
this.interceptScript = false;
|
|
121
|
+
// rewrite JavaScript Code in browser
|
|
120
122
|
this.instrumentJS = false;
|
|
121
123
|
// external heap snapshot paths, if enabled
|
|
122
124
|
this.externalSnapshotFilePaths = [];
|
|
@@ -139,8 +141,15 @@ class MemLabConfig {
|
|
|
139
141
|
this.mlMaxDF = 1;
|
|
140
142
|
// if true, evaluating results with sequential clustering
|
|
141
143
|
this.isSequentialClustering = false;
|
|
144
|
+
// if true, evaluating results with sequential
|
|
145
|
+
// clustering with multiple iterations
|
|
146
|
+
this.isMultiIterationSeqClustering = false;
|
|
142
147
|
// split the sample leak traces into 4 smaller ones by default.
|
|
143
148
|
this.seqClusteringSplitCount = 4;
|
|
149
|
+
// the number of iterations for multi-iteration sequential clustering
|
|
150
|
+
this.multiIterSeqClusteringIteration = 1;
|
|
151
|
+
// the number of trace samples to retain from each cluster
|
|
152
|
+
this.multiIterSeqClusteringSampleSize = Infinity;
|
|
144
153
|
// if true, split dataset into trunks
|
|
145
154
|
// with random order for sequential clustering
|
|
146
155
|
this.seqClusteringIsRandomChunks = false;
|
package/dist/lib/Console.d.ts
CHANGED
|
@@ -23,6 +23,7 @@ declare class MemLabConsole {
|
|
|
23
23
|
private config;
|
|
24
24
|
private sections;
|
|
25
25
|
private log;
|
|
26
|
+
private logFileSet;
|
|
26
27
|
private styles;
|
|
27
28
|
private static singleton;
|
|
28
29
|
protected constructor();
|
|
@@ -40,6 +41,8 @@ declare class MemLabConsole {
|
|
|
40
41
|
private shouldBeConcise;
|
|
41
42
|
private clearPrevOverwriteMsg;
|
|
42
43
|
private printStr;
|
|
44
|
+
registerLogFile(logFile: string): void;
|
|
45
|
+
unregisterLogFile(logFile: string): void;
|
|
43
46
|
beginSection(name: string): void;
|
|
44
47
|
endSection(name: string): void;
|
|
45
48
|
setConfig(config: MemLabConfig): void;
|
package/dist/lib/Console.js
CHANGED
|
@@ -14,10 +14,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
const chalk_1 = __importDefault(require("chalk"));
|
|
16
16
|
const fs_1 = __importDefault(require("fs"));
|
|
17
|
+
const path_1 = __importDefault(require("path"));
|
|
17
18
|
const readline_1 = __importDefault(require("readline"));
|
|
18
19
|
const string_width_1 = __importDefault(require("string-width"));
|
|
19
20
|
const stdout = process.stdout;
|
|
20
21
|
const TABLE_MAX_WIDTH = 50;
|
|
22
|
+
const LOG_BUFFER_LENGTH = 100;
|
|
21
23
|
const prevLine = '\x1b[F';
|
|
22
24
|
const eraseLine = '\x1b[K';
|
|
23
25
|
const barComplete = chalk_1.default.green('\u2588');
|
|
@@ -42,10 +44,21 @@ function formatTableArg(arg) {
|
|
|
42
44
|
}
|
|
43
45
|
});
|
|
44
46
|
}
|
|
47
|
+
function registerExitCleanup(inst, exitHandler) {
|
|
48
|
+
const p = process;
|
|
49
|
+
// normal exit
|
|
50
|
+
p.on('exit', exitHandler.bind(null, { cleanup: true }));
|
|
51
|
+
// ctrl + c event
|
|
52
|
+
p.on('SIGINT', exitHandler.bind(null, { exit: true }));
|
|
53
|
+
// kill pid
|
|
54
|
+
p.on('SIGUSR1', exitHandler.bind(null, { exit: true }));
|
|
55
|
+
p.on('SIGUSR2', exitHandler.bind(null, { exit: true }));
|
|
56
|
+
}
|
|
45
57
|
class MemLabConsole {
|
|
46
58
|
constructor() {
|
|
47
59
|
this.config = {};
|
|
48
60
|
this.log = [];
|
|
61
|
+
this.logFileSet = new Set();
|
|
49
62
|
this.styles = {
|
|
50
63
|
top: (msg) => msg,
|
|
51
64
|
high: chalk_1.default.dim.bind(chalk_1.default),
|
|
@@ -67,12 +80,15 @@ class MemLabConsole {
|
|
|
67
80
|
}
|
|
68
81
|
const inst = new MemLabConsole();
|
|
69
82
|
MemLabConsole.singleton = inst;
|
|
70
|
-
|
|
83
|
+
const exitHandler = (
|
|
84
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
85
|
+
_options,
|
|
71
86
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
72
|
-
|
|
73
|
-
inst.flushLog();
|
|
87
|
+
_exitCode) => {
|
|
88
|
+
inst.flushLog({ sync: true });
|
|
74
89
|
inst.clearPrevOverwriteMsg();
|
|
75
|
-
}
|
|
90
|
+
};
|
|
91
|
+
registerExitCleanup(inst, exitHandler);
|
|
76
92
|
return inst;
|
|
77
93
|
}
|
|
78
94
|
style(msg, name) {
|
|
@@ -98,28 +114,49 @@ class MemLabConsole {
|
|
|
98
114
|
}
|
|
99
115
|
logMsg(msg) {
|
|
100
116
|
// remove control characters
|
|
101
|
-
const
|
|
117
|
+
const lines = msg.split('\n').map(line => line
|
|
102
118
|
// eslint-disable-next-line no-control-regex
|
|
103
119
|
.replace(/[\u0000-\u001F\u007F-\u009F]/g, '')
|
|
104
|
-
.replace(/\[\d{1,3}m/g, '');
|
|
105
|
-
this.log.push(
|
|
106
|
-
if (this.log.length >
|
|
107
|
-
this.flushLog();
|
|
120
|
+
.replace(/\[\d{1,3}m/g, ''));
|
|
121
|
+
this.log.push(...lines);
|
|
122
|
+
if (this.log.length > LOG_BUFFER_LENGTH) {
|
|
123
|
+
this.flushLog({ sync: true });
|
|
108
124
|
}
|
|
109
125
|
}
|
|
110
|
-
flushLog() {
|
|
126
|
+
flushLog(options = {}) {
|
|
111
127
|
const str = this.log.join('\n');
|
|
112
|
-
if (str.length > 0) {
|
|
113
|
-
const file = this.config.consoleLogFile;
|
|
114
|
-
fs_1.default.appendFile(file, str + '\n', 'UTF-8', () => {
|
|
115
|
-
// NOOP
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
128
|
this.log = [];
|
|
129
|
+
if (str.length === 0) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
// synchronous logging
|
|
133
|
+
if (options.sync) {
|
|
134
|
+
for (const logFile of this.logFileSet) {
|
|
135
|
+
try {
|
|
136
|
+
fs_1.default.appendFileSync(logFile, str + '\n', 'UTF-8');
|
|
137
|
+
}
|
|
138
|
+
catch (_a) {
|
|
139
|
+
// fail silently
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
// async logging
|
|
145
|
+
const emptyCallback = () => {
|
|
146
|
+
// no op
|
|
147
|
+
};
|
|
148
|
+
for (const logFile of this.logFileSet) {
|
|
149
|
+
try {
|
|
150
|
+
fs_1.default.appendFile(logFile, str + '\n', 'UTF-8', emptyCallback);
|
|
151
|
+
}
|
|
152
|
+
catch (_b) {
|
|
153
|
+
// fail silently
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
119
157
|
}
|
|
120
158
|
pushMsg(msg, options = {}) {
|
|
121
|
-
|
|
122
|
-
if (this.config.isContinuousTest || len === 0) {
|
|
159
|
+
if (this.sections.arr.length === 0) {
|
|
123
160
|
return;
|
|
124
161
|
}
|
|
125
162
|
// calculate each line's visible width
|
|
@@ -140,7 +177,9 @@ class MemLabConsole {
|
|
|
140
177
|
if (!section || section.msgs.length === 0) {
|
|
141
178
|
return;
|
|
142
179
|
}
|
|
143
|
-
|
|
180
|
+
if (!this.config.muteConsole) {
|
|
181
|
+
stdout.write(eraseLine);
|
|
182
|
+
}
|
|
144
183
|
const msg = section.msgs.pop();
|
|
145
184
|
if (!msg) {
|
|
146
185
|
return;
|
|
@@ -150,8 +189,10 @@ class MemLabConsole {
|
|
|
150
189
|
const line = (_a = lines.pop()) !== null && _a !== void 0 ? _a : 0;
|
|
151
190
|
const width = stdout.columns;
|
|
152
191
|
let n = line === 0 ? 1 : Math.ceil(line / width);
|
|
153
|
-
|
|
154
|
-
|
|
192
|
+
if (!this.config.muteConsole && !this.config.isTest) {
|
|
193
|
+
while (n-- > 0) {
|
|
194
|
+
stdout.write(prevLine + eraseLine);
|
|
195
|
+
}
|
|
155
196
|
}
|
|
156
197
|
}
|
|
157
198
|
}
|
|
@@ -189,11 +230,21 @@ class MemLabConsole {
|
|
|
189
230
|
this.clearPrevMsgInLastSection();
|
|
190
231
|
}
|
|
191
232
|
printStr(msg, options = {}) {
|
|
192
|
-
|
|
233
|
+
this.pushMsg(msg, options);
|
|
234
|
+
if (this.config.isTest) {
|
|
193
235
|
return;
|
|
194
236
|
}
|
|
195
|
-
|
|
196
|
-
|
|
237
|
+
if (this.config.isContinuousTest || !this.config.muteConsole) {
|
|
238
|
+
console.log(msg);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
registerLogFile(logFile) {
|
|
242
|
+
this.flushLog({ sync: true });
|
|
243
|
+
this.logFileSet.add(path_1.default.resolve(logFile));
|
|
244
|
+
}
|
|
245
|
+
unregisterLogFile(logFile) {
|
|
246
|
+
this.flushLog({ sync: true });
|
|
247
|
+
this.logFileSet.delete(path_1.default.resolve(logFile));
|
|
197
248
|
}
|
|
198
249
|
beginSection(name) {
|
|
199
250
|
if (this.config.isContinuousTest) {
|
|
@@ -300,14 +351,16 @@ class MemLabConsole {
|
|
|
300
351
|
this.printStr('');
|
|
301
352
|
}
|
|
302
353
|
overwrite(msg, options = {}) {
|
|
303
|
-
|
|
354
|
+
const str = this.style(msg, options.level || 'low');
|
|
355
|
+
if (this.config.isContinuousTest) {
|
|
356
|
+
this.printStr(msg, { isOverwrite: false });
|
|
304
357
|
return;
|
|
305
358
|
}
|
|
306
|
-
if (this.config.
|
|
307
|
-
|
|
359
|
+
if (this.config.isTest || this.config.muteConsole) {
|
|
360
|
+
this.printStr(str, { isOverwrite: true });
|
|
361
|
+
return;
|
|
308
362
|
}
|
|
309
363
|
this.clearPrevOverwriteMsg();
|
|
310
|
-
const str = this.style(msg, options.level || 'low');
|
|
311
364
|
this.printStr(str, { isOverwrite: true });
|
|
312
365
|
}
|
|
313
366
|
waitForConsole(query) {
|
|
@@ -32,8 +32,11 @@ export declare class FileManager {
|
|
|
32
32
|
getCurDataDir(options: FileOption): string;
|
|
33
33
|
getWebSourceDir(options?: FileOption): string;
|
|
34
34
|
getWebSourceMetaFile(options?: FileOption): string;
|
|
35
|
+
getDebugDataDir(options?: FileOption): string;
|
|
36
|
+
getDebugSourceFile(options?: FileOption): string;
|
|
35
37
|
getPersistDataDir(options: FileOption): string;
|
|
36
38
|
getLoggerOutDir(options?: FileOption): string;
|
|
39
|
+
getHeapAnalysisLogDir(options?: FileOption): string;
|
|
37
40
|
getTraceClustersDir(options?: FileOption): string;
|
|
38
41
|
getTraceJSONDir(options?: FileOption): string;
|
|
39
42
|
getUnclassifiedTraceClusterDir(options?: FileOption): string;
|
|
@@ -61,6 +64,7 @@ export declare class FileManager {
|
|
|
61
64
|
controlWorkDir: string;
|
|
62
65
|
testWorkDir: string;
|
|
63
66
|
};
|
|
67
|
+
initNewHeapAnalysisLogFile(options?: FileOption): string;
|
|
64
68
|
getAndInitTSCompileIntermediateDir(): string;
|
|
65
69
|
clearDataDirs(options?: FileOption): void;
|
|
66
70
|
emptyDirIfExists(dir: string): void;
|
package/dist/lib/FileManager.js
CHANGED
|
@@ -98,12 +98,22 @@ class FileManager {
|
|
|
98
98
|
getWebSourceMetaFile(options = {}) {
|
|
99
99
|
return path_1.default.join(this.getWebSourceDir(options), 'files.json');
|
|
100
100
|
}
|
|
101
|
+
getDebugDataDir(options = {}) {
|
|
102
|
+
return path_1.default.join(this.getDataBaseDir(options), 'debug');
|
|
103
|
+
}
|
|
104
|
+
getDebugSourceFile(options = {}) {
|
|
105
|
+
return path_1.default.join(this.getDebugDataDir(options), 'file.js');
|
|
106
|
+
}
|
|
101
107
|
getPersistDataDir(options) {
|
|
102
108
|
return path_1.default.join(this.getDataBaseDir(options), 'persist');
|
|
103
109
|
}
|
|
104
110
|
getLoggerOutDir(options = {}) {
|
|
105
111
|
return path_1.default.join(this.getDataBaseDir(options), 'logger');
|
|
106
112
|
}
|
|
113
|
+
// all heap analysis results generated
|
|
114
|
+
getHeapAnalysisLogDir(options = {}) {
|
|
115
|
+
return path_1.default.join(this.getLoggerOutDir(options), 'heap-analysis');
|
|
116
|
+
}
|
|
107
117
|
// all trace clusters generated from the current run
|
|
108
118
|
getTraceClustersDir(options = {}) {
|
|
109
119
|
return path_1.default.join(this.getLoggerOutDir(options), 'trace-clusters');
|
|
@@ -200,6 +210,15 @@ class FileManager {
|
|
|
200
210
|
const testWorkDir = joinAndProcessDir({}, expDir, 'test');
|
|
201
211
|
return { controlWorkDir, testWorkDir };
|
|
202
212
|
}
|
|
213
|
+
// create a unique log file created for heap analysis output
|
|
214
|
+
initNewHeapAnalysisLogFile(options = {}) {
|
|
215
|
+
const dir = this.getHeapAnalysisLogDir(options);
|
|
216
|
+
const file = path_1.default.join(dir, `analysis-${Utils_1.default.getUniqueID()}-out.log`);
|
|
217
|
+
if (!fs_extra_1.default.existsSync(file)) {
|
|
218
|
+
fs_extra_1.default.createFileSync(file);
|
|
219
|
+
}
|
|
220
|
+
return file;
|
|
221
|
+
}
|
|
203
222
|
getAndInitTSCompileIntermediateDir() {
|
|
204
223
|
const dir = path_1.default.join(this.getTmpDir(), 'memlab-code');
|
|
205
224
|
this.rmDir(dir);
|
|
@@ -212,6 +231,7 @@ class FileManager {
|
|
|
212
231
|
return;
|
|
213
232
|
}
|
|
214
233
|
this.emptyDirIfExists(this.getWebSourceDir(options));
|
|
234
|
+
this.emptyDirIfExists(this.getDebugDataDir(options));
|
|
215
235
|
const dataSuffix = ['.heapsnapshot', '.json', '.png'];
|
|
216
236
|
const files = fs_extra_1.default.readdirSync(curDataDir);
|
|
217
237
|
for (const file of files) {
|
|
@@ -238,6 +258,8 @@ class FileManager {
|
|
|
238
258
|
this.emptyDirIfExists(this.getUnclassifiedTraceClusterDir(options));
|
|
239
259
|
// all unique cluster info
|
|
240
260
|
this.emptyDirIfExists(this.getUniqueTraceClusterDir(options));
|
|
261
|
+
// all heap analysis results
|
|
262
|
+
this.emptyDirIfExists(this.getHeapAnalysisLogDir(options));
|
|
241
263
|
}
|
|
242
264
|
resetBrowserDir() {
|
|
243
265
|
try {
|
|
@@ -294,9 +316,12 @@ class FileManager {
|
|
|
294
316
|
const outDir = joinAndProcessDir(options, this.getDataOutDir(options));
|
|
295
317
|
config.curDataDir = joinAndProcessDir(options, this.getCurDataDir(options));
|
|
296
318
|
config.webSourceDir = joinAndProcessDir(options, this.getWebSourceDir(options));
|
|
319
|
+
config.debugDataDir = joinAndProcessDir(options, this.getDebugDataDir(options));
|
|
297
320
|
config.dataBuilderDataDir = joinAndProcessDir(options, config.dataBaseDir, 'dataBuilder');
|
|
298
321
|
config.persistentDataDir = joinAndProcessDir(options, this.getPersistDataDir(options));
|
|
322
|
+
// register the default log file
|
|
299
323
|
config.consoleLogFile = path_1.default.join(config.curDataDir, 'console-log.txt');
|
|
324
|
+
Console_1.default.registerLogFile(config.consoleLogFile);
|
|
300
325
|
config.runMetaFile = this.getRunMetaFile(options);
|
|
301
326
|
config.snapshotSequenceFile = this.getSnapshotSequenceMetaFile(options);
|
|
302
327
|
config.browserInfoSummary = path_1.default.join(config.curDataDir, 'browser-info.txt');
|
|
@@ -314,6 +339,8 @@ class FileManager {
|
|
|
314
339
|
config.traceClusterOutDir = joinAndProcessDir(options, this.getTraceClustersDir(options));
|
|
315
340
|
// detailed trace json files for visualization
|
|
316
341
|
config.traceJsonOutDir = joinAndProcessDir(options, this.getTraceJSONDir(options));
|
|
342
|
+
// heap analysis results
|
|
343
|
+
config.heapAnalysisLogDir = joinAndProcessDir(options, this.getHeapAnalysisLogDir(options));
|
|
317
344
|
config.metricsOutDir = joinAndProcessDir(options, loggerOutDir, 'metrics');
|
|
318
345
|
config.reportScreenshotFile = path_1.default.join(outDir, 'report.png');
|
|
319
346
|
const codeDataDir = this.getCodeDataDir();
|
|
@@ -7,15 +7,10 @@
|
|
|
7
7
|
* @format
|
|
8
8
|
* @oncall web_perf_infra
|
|
9
9
|
*/
|
|
10
|
-
import type { E2EStepInfo, HeapNodeIdSet,
|
|
10
|
+
import type { E2EStepInfo, HeapNodeIdSet, IHeapSnapshot, IMemoryAnalystOptions, IMemoryAnalystSnapshotDiff, IOveralHeapInfo, LeakTracePathItem, Optional, IOveralLeakInfo, TraceCluster, ISerializedInfo } from './Types';
|
|
11
11
|
import TraceFinder from '../paths/TraceFinder';
|
|
12
12
|
declare class MemoryAnalyst {
|
|
13
13
|
checkLeak(): Promise<ISerializedInfo[]>;
|
|
14
|
-
checkUnbound(options?: IMemoryAnalystOptions): Promise<void>;
|
|
15
|
-
breakDownMemoryByShapes(options?: {
|
|
16
|
-
file?: string;
|
|
17
|
-
}): Promise<void>;
|
|
18
|
-
detectUnboundGrowth(options?: IMemoryAnalystOptions): Promise<void>;
|
|
19
14
|
detectMemoryLeaks(): Promise<ISerializedInfo[]>;
|
|
20
15
|
visualizeMemoryUsage(options?: IMemoryAnalystOptions): void;
|
|
21
16
|
focus(options?: {
|
|
@@ -23,19 +18,15 @@ declare class MemoryAnalyst {
|
|
|
23
18
|
}): Promise<void>;
|
|
24
19
|
shouldLoadCompleteSnapshot(tabsOrder: E2EStepInfo[], tab: E2EStepInfo): boolean;
|
|
25
20
|
diffSnapshots(loadAll?: boolean): Promise<IMemoryAnalystSnapshotDiff>;
|
|
26
|
-
private calculateRetainedSizes;
|
|
27
21
|
preparePathFinder(snapshot: IHeapSnapshot): TraceFinder;
|
|
28
22
|
private dumpPageInteractionSummary;
|
|
29
23
|
private dumpLeakSummaryToConsole;
|
|
30
24
|
private filterLeakedObjects;
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
25
|
+
getOverallHeapInfo(snapshot: IHeapSnapshot, options?: {
|
|
26
|
+
force?: boolean;
|
|
27
|
+
}): Optional<IOveralHeapInfo>;
|
|
34
28
|
getOverallLeakInfo(leakedNodeIds: HeapNodeIdSet, snapshot: IHeapSnapshot): Optional<IOveralLeakInfo>;
|
|
35
|
-
|
|
36
|
-
private breakDownSnapshotByShapes;
|
|
37
|
-
private isTrivialEdgeForBreakDown;
|
|
38
|
-
private breakDownByReferrers;
|
|
29
|
+
printHeapInfo(leakInfo: IOveralHeapInfo): void;
|
|
39
30
|
private printHeapAndLeakInfo;
|
|
40
31
|
private logLeakTraceSummary;
|
|
41
32
|
searchLeakedTraces(leakedNodeIds: HeapNodeIdSet, snapshot: IHeapSnapshot): Promise<{
|