UNPKG

13.7 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.MemoryLeakDetector = exports.FunctionCpuUsage = exports.FunctionStatsMap = exports.FactoryMap = void 0;
4const provider_1 = require("./provider");
5const shared_1 = require("./shared");
6class FactoryMap extends Map {
7 constructor(factory) {
8 super();
9 this.factory = factory;
10 }
11 getOrCreate(key) {
12 let val = this.get(key);
13 if (!val) {
14 val = this.factory(key);
15 this.set(key, val);
16 }
17 return val;
18 }
19}
20exports.FactoryMap = FactoryMap;
21class FunctionStatsMap {
22 constructor() {
23 this.fIncremental = new FactoryMap(() => new provider_1.FunctionStats());
24 this.fAggregate = new FactoryMap(() => new provider_1.FunctionStats());
25 this.aggregate = new provider_1.FunctionStats();
26 }
27 update(fn, key, value) {
28 this.fIncremental.getOrCreate(fn)[key].update(value);
29 this.fAggregate.getOrCreate(fn)[key].update(value);
30 this.aggregate[key].update(value);
31 }
32 incr(fn, key, n = 1) {
33 this.fIncremental.getOrCreate(fn)[key] += n;
34 this.fAggregate.getOrCreate(fn)[key] += n;
35 this.aggregate[key] += n;
36 }
37 resetIncremental() {
38 this.fIncremental.clear();
39 }
40 toString() {
41 return [...this.fAggregate].map(([key, value]) => `[${key}] ${value}`).join("\n");
42 }
43 clear() {
44 this.fIncremental.clear();
45 this.fAggregate.clear();
46 }
47}
48exports.FunctionStatsMap = FunctionStatsMap;
49class FunctionCpuUsage {
50 constructor() {
51 this.utime = new shared_1.Statistics();
52 this.stime = new shared_1.Statistics();
53 this.cpuTime = new shared_1.Statistics();
54 this.smallest = new shared_1.SmallestN(100);
55 }
56}
57exports.FunctionCpuUsage = FunctionCpuUsage;
58class FunctionMemoryStats {
59 constructor() {
60 this.rss = new shared_1.Statistics();
61 this.heapTotal = new shared_1.Statistics();
62 this.heapUsed = new shared_1.Statistics();
63 this.external = new shared_1.Statistics();
64 }
65}
66class FunctionMemoryCounters {
67 constructor() {
68 this.heapUsedGrowth = 0;
69 this.externalGrowth = 0;
70 }
71}
72class MemoryLeakDetector {
73 constructor(memorySize) {
74 this.instances = new FactoryMap(() => new FunctionMemoryStats());
75 this.counters = new FactoryMap(() => new FunctionMemoryCounters());
76 this.warned = new Set();
77 this.memorySize = memorySize || 100;
78 }
79 detectedNewLeak(fn, instanceId, memoryUsage) {
80 if (this.warned.has(fn)) {
81 return false;
82 }
83 const { rss, heapTotal, heapUsed, external } = memoryUsage;
84 const instanceStats = this.instances.getOrCreate(instanceId);
85 const counters = this.counters.getOrCreate(instanceId);
86 if (heapUsed > instanceStats.heapUsed.max) {
87 counters.heapUsedGrowth++;
88 }
89 else {
90 counters.heapUsedGrowth = 0;
91 }
92 if (external > instanceStats.external.max) {
93 counters.externalGrowth++;
94 }
95 else {
96 counters.externalGrowth = 0;
97 }
98 instanceStats.rss.update(rss);
99 instanceStats.heapTotal.update(heapTotal);
100 instanceStats.heapUsed.update(heapUsed);
101 instanceStats.external.update(external);
102 if (heapUsed > this.memorySize * 0.8 * 2 ** 20 ||
103 external > this.memorySize * 0.8 * 2 ** 20) {
104 if (counters.heapUsedGrowth > 4 || counters.externalGrowth > 4) {
105 this.warned.add(fn);
106 return true;
107 }
108 }
109 return false;
110 }
111 clear() {
112 this.instances.clear();
113 this.counters.clear();
114 this.warned.clear();
115 }
116}
117exports.MemoryLeakDetector = MemoryLeakDetector;
118//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWV0cmljcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9tZXRyaWNzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHlDQUEyQztBQUMzQyxxQ0FBaUQ7QUFHakQsTUFBYSxVQUErQixTQUFRLEdBQVM7SUFDekQsWUFBcUIsT0FBc0I7UUFDdkMsS0FBSyxFQUFFLENBQUM7UUFEUyxZQUFPLEdBQVAsT0FBTyxDQUFlO0lBRTNDLENBQUM7SUFFRCxXQUFXLENBQUMsR0FBTTtRQUNkLElBQUksR0FBRyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDeEIsSUFBSSxDQUFDLEdBQUcsRUFBRTtZQUNOLEdBQUcsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ3hCLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDO1NBQ3RCO1FBQ0QsT0FBTyxHQUFHLENBQUM7SUFDZixDQUFDO0NBQ0o7QUFiRCxnQ0FhQztBQUVELE1BQWEsZ0JBQWdCO0lBQTdCO1FBQ0ksaUJBQVksR0FBRyxJQUFJLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLHdCQUFhLEVBQUUsQ0FBQyxDQUFDO1FBQ3pELGVBQVUsR0FBRyxJQUFJLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLHdCQUFhLEVBQUUsQ0FBQyxDQUFDO1FBQ3ZELGNBQVMsR0FBRyxJQUFJLHdCQUFhLEVBQUUsQ0FBQztJQThCcEMsQ0FBQztJQTVCRyxNQUFNLENBQ0YsRUFBVSxFQUNWLEdBQXNELEVBQ3RELEtBQWE7UUFFYixJQUFJLENBQUMsWUFBWSxDQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDckQsSUFBSSxDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFD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QixJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQ3hCLENBQUM7Q0FDSjtBQWpERCxnREFpREMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBGdW5jdGlvblN0YXRzIH0gZnJvbSBcIi4vcHJvdmlkZXJcIjtcbmltcG9ydCB7IFNtYWxsZXN0TiwgU3RhdGlzdGljcyB9IGZyb20gXCIuL3NoYXJlZFwiO1xuaW1wb3J0IHsgUHJvcGVydGllc09mVHlwZSB9IGZyb20gXCIuL3R5cGVzXCI7XG5cbmV4cG9ydCBjbGFzcyBGYWN0b3J5TWFwPEsgPSBzdHJpbmcsIFYgPSB7fT4gZXh0ZW5kcyBNYXA8SywgVj4ge1xuICAgIGNvbnN0cnVjdG9yKHJlYWRvbmx5IGZhY3Rvcnk6IChrZXk6IEspID0+IFYpIHtcbiAgICAgICAgc3VwZXIoKTtcbiAgICB9XG5cbiAgICBnZXRPckNyZWF0ZShrZXk6IEspIHtcbiAgICAgICAgbGV0IHZhbCA9IHRoaXMuZ2V0KGtleSk7XG4gICAgICAgIGlmICghdmFsKSB7XG4gICAgICAgICAgICB2YWwgPSB0aGlzLmZhY3Rvcnkoa2V5KTtcbiAgICAgICAgICAgIHRoaXMuc2V0KGtleSwgdmFsKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdmFsO1xuICAgIH1cbn1cblxuZXhwb3J0IGNsYXNzIEZ1bmN0aW9uU3RhdHNNYXAge1xuICAgIGZJbmNyZW1lbnRhbCA9IG5ldyBGYWN0b3J5TWFwKCgpID0+IG5ldyBGdW5jdGlvblN0YXRzKCkpO1xuICAgIGZBZ2dyZWdhdGUgPSBuZXcgRmFjdG9yeU1hcCgoKSA9PiBuZXcgRnVuY3Rpb25TdGF0cygpKTtcbiAgICBhZ2dyZWdhdGUgPSBuZXcgRnVuY3Rpb25TdGF0cygpO1xuXG4gICAgdXBkYXRlKFxuICAgICAgICBmbjogc3RyaW5nLFxuICAgICAgICBrZXk6IGtleW9mIFByb3BlcnRpZXNPZlR5cGU8RnVuY3Rpb25TdGF0cywgU3RhdGlzdGljcz4sXG4gICAgICAgIHZhbHVlOiBudW1iZXJcbiAgICApIHtcbiAgICAgICAgdGhpcy5mSW5jcmVtZW50YWwuZ2V0T3JDcmVhdGUoZm4pW2tleV0udXBkYXRlKHZhbHVlKTtcbiAgICAgICAgdGhpcy5mQWdncmVnYXRlLmdldE9yQ3JlYXRlKGZuKVtrZXldLnVwZGF0ZSh2YWx1ZSk7XG4gICAgICAgIHRoaXMuYWdncmVnYXRlW2tleV0udXBkYXRlKHZhbHVlKTtcbiAgICB9XG5cbiAgICBpbmNyKGZuOiBzdHJpbmcsIGtleToga2V5b2YgUHJvcGVydGllc09mVHlwZTxGdW5jdGlvblN0YXRzLCBudW1iZXI+LCBuOiBudW1iZXIgPSAxKSB7XG4gICAgICAgIHRoaXMuZkluY3JlbWVudGFsLmdldE9yQ3JlYXRlKGZuKVtrZXldICs9IG47XG4gICAgICAgIHRoaXMuZkFnZ3JlZ2F0ZS5nZXRPckNyZWF0ZShmbilba2V5XSArPSBuO1xuICAgICAgICB0aGlzLmFnZ3JlZ2F0ZVtrZXldICs9IG47XG4gICAgfVxuXG4gICAgcmVzZXRJbmNyZW1lbnRhbCgpIHtcbiAgICAgICAgdGhpcy5mSW5jcmVtZW50YWwuY2xlYXIoKTtcbiAgICB9XG5cbiAgICB0b1N0cmluZygpIHtcbiAgICAgICAgcmV0dXJuIFsuLi50aGlzLmZBZ2dyZWdhdGVdLm1hcCgoW2tleSwgdmFsdWVdKSA9PiBgWyR7a2V5fV0gJHt2YWx1ZX1gKS5qb2luKFwiXFxuXCIpO1xuICAgIH1cblxuICAgIGNsZWFyKCkge1xuICAgICAgICB0aGlzLmZJbmNyZW1lbnRhbC5jbGVhcigpO1xuICAgICAgICB0aGlzLmZBZ2dyZWdhdGUuY2xlYXIoKTtcbiAgICB9XG59XG5cbmV4cG9ydCBjbGFzcyBGdW5jdGlvbkNwdVVzYWdlIHtcbiAgICB1dGltZSA9IG5ldyBTdGF0aXN0aWNzKCk7XG4gICAgc3RpbWUgPSBuZXcgU3RhdGlzdGljcygpO1xuICAgIGNwdVRpbWUgPSBuZXcgU3RhdGlzdGljcygpO1xuICAgIHNtYWxsZXN0ID0gbmV3IFNtYWxsZXN0TigxMDApO1xufVxuXG5jbGFzcyBGdW5jdGlvbk1lbW9yeVN0YXRzIHtcbiAgICByc3MgPSBuZXcgU3RhdGlzdGljcygpO1xuICAgIGhlYXBUb3RhbCA9IG5ldyBTdGF0aXN0aWNzKCk7XG4gICAgaGVhcFVzZWQgPSBuZXcgU3RhdGlzdGljcygpO1xuICAgIGV4dGVybmFsID0gbmV3IFN0YXRpc3RpY3MoKTtcbn1cblxuY2xhc3MgRnVuY3Rpb25NZW1vcnlDb3VudGVycyB7XG4gICAgaGVhcFVzZWRHcm93dGggPSAwO1xuICAgIGV4dGVybmFsR3Jvd3RoID0gMDtcbn1cblxuZXhwb3J0IGNsYXNzIE1lbW9yeUxlYWtEZXRlY3RvciB7XG4gICAgcHJpdmF0ZSBpbnN0YW5jZXMgPSBuZXcgRmFjdG9yeU1hcCgoKSA9PiBuZXcgRnVuY3Rpb25NZW1vcnlTdGF0cygpKTtcbiAgICBwcml2YXRlIGNvdW50ZXJzID0gbmV3IEZhY3RvcnlNYXAoKCkgPT4gbmV3IEZ1bmN0aW9uTWVtb3J5Q291bnRlcnMoKSk7XG4gICAgcHJpdmF0ZSB3YXJuZWQgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICBwcml2YXRlIG1lbW9yeVNpemU6IG51bWJlcjtcblxuICAgIGNvbnN0cnVjdG9yKG1lbW9yeVNpemU/OiBudW1iZXIpIHtcbiAgICAgICAgdGhpcy5tZW1vcnlTaXplID0gbWVtb3J5U2l6ZSB8fCAxMDA7XG4gICAgfVxuXG4gICAgZGV0ZWN0ZWROZXdMZWFrKGZuOiBzdHJpbmcsIGluc3RhbmNlSWQ6IHN0cmluZywgbWVtb3J5VXNhZ2U6IE5vZGVKUy5NZW1vcnlVc2FnZSkge1xuICAgICAgICBpZiAodGhpcy53YXJuZWQuaGFzKGZuKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHsgcnNzLCBoZWFwVG90YWwsIGhlYXBVc2VkLCBleHRlcm5hbCB9ID0gbWVtb3J5VXNhZ2U7XG4gICAgICAgIGNvbnN0IGluc3RhbmNlU3RhdHMgPSB0aGlzLmluc3RhbmNlcy5nZXRPckNyZWF0ZShpbnN0YW5jZUlkKTtcbiAgICAgICAgY29uc3QgY291bnRlcnMgPSB0aGlzLmNvdW50ZXJzLmdldE9yQ3JlYXRlKGluc3RhbmNlSWQpO1xuICAgICAgICBpZiAoaGVhcFVzZWQgPiBpbnN0YW5jZVN0YXRzLmhlYXBVc2VkLm1heCkge1xuICAgICAgICAgICAgY291bnRlcnMuaGVhcFVzZWRHcm93dGgrKztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvdW50ZXJzLmhlYXBVc2VkR3Jvd3RoID0gMDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZXh0ZXJuYWwgPiBpbnN0YW5jZVN0YXRzLmV4dGVybmFsLm1heCkge1xuICAgICAgICAgICAgY291bnRlcnMuZXh0ZXJuYWxHcm93dGgrKztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvdW50ZXJzLmV4dGVybmFsR3Jvd3RoID0gMDtcbiAgICAgICAgfVxuICAgICAgICBpbnN0YW5jZVN0YXRzLnJzcy51cGRhdGUocnNzKTtcbiAgICAgICAgaW5zdGFuY2VTdGF0cy5oZWFwVG90YWwudXBkYXRlKGhlYXBUb3RhbCk7XG4gICAgICAgIGluc3RhbmNlU3RhdHMuaGVhcFVzZWQudXBkYXRlKGhlYXBVc2VkKTtcbiAgICAgICAgaW5zdGFuY2VTdGF0cy5leHRlcm5hbC51cGRhdGUoZXh0ZXJuYWwpO1xuXG4gICAgICAgIGlmIChcbiAgICAgICAgICAgIGhlYXBVc2VkID4gdGhpcy5tZW1vcnlTaXplICogMC44ICogMiAqKiAyMCB8fFxuICAgICAgICAgICAgZXh0ZXJuYWwgPiB0aGlzLm1lbW9yeVNpemUgKiAwLjggKiAyICoqIDIwXG4gICAgICAgICkge1xuICAgICAgICAgICAgaWYgKGNvdW50ZXJzLmhlYXBVc2VkR3Jvd3RoID4gNCB8fCBjb3VudGVycy5leHRlcm5hbEdyb3d0aCA+IDQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLndhcm5lZC5hZGQoZm4pO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBjbGVhcigpIHtcbiAgICAgICAgdGhpcy5pbnN0YW5jZXMuY2xlYXIoKTtcbiAgICAgICAgdGhpcy5jb3VudGVycy5jbGVhcigpO1xuICAgICAgICB0aGlzLndhcm5lZC5jbGVhcigpO1xuICAgIH1cbn1cbiJdfQ==
\No newline at end of file