faastjs
Version:
Serverless batch computing made simple.
118 lines • 13.8 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MemoryLeakDetector = exports.FunctionCpuUsage = exports.FunctionStatsMap = exports.FactoryMap = void 0;
const provider_1 = require("./provider");
const shared_1 = require("./shared");
class FactoryMap extends Map {
constructor(factory) {
super();
this.factory = factory;
}
getOrCreate(key) {
let val = this.get(key);
if (!val) {
val = this.factory(key);
this.set(key, val);
}
return val;
}
}
exports.FactoryMap = FactoryMap;
class FunctionStatsMap {
constructor() {
this.fIncremental = new FactoryMap(() => new provider_1.FunctionStats());
this.fAggregate = new FactoryMap(() => new provider_1.FunctionStats());
this.aggregate = new provider_1.FunctionStats();
}
update(fn, key, value) {
this.fIncremental.getOrCreate(fn)[key].update(value);
this.fAggregate.getOrCreate(fn)[key].update(value);
this.aggregate[key].update(value);
}
incr(fn, key, n = 1) {
this.fIncremental.getOrCreate(fn)[key] += n;
this.fAggregate.getOrCreate(fn)[key] += n;
this.aggregate[key] += n;
}
resetIncremental() {
this.fIncremental.clear();
}
toString() {
return [...this.fAggregate].map(([key, value]) => `[${key}] ${value}`).join("\n");
}
clear() {
this.fIncremental.clear();
this.fAggregate.clear();
}
}
exports.FunctionStatsMap = FunctionStatsMap;
class FunctionCpuUsage {
constructor() {
this.utime = new shared_1.Statistics();
this.stime = new shared_1.Statistics();
this.cpuTime = new shared_1.Statistics();
this.smallest = new shared_1.SmallestN(100);
}
}
exports.FunctionCpuUsage = FunctionCpuUsage;
class FunctionMemoryStats {
constructor() {
this.rss = new shared_1.Statistics();
this.heapTotal = new shared_1.Statistics();
this.heapUsed = new shared_1.Statistics();
this.external = new shared_1.Statistics();
}
}
class FunctionMemoryCounters {
constructor() {
this.heapUsedGrowth = 0;
this.externalGrowth = 0;
}
}
class MemoryLeakDetector {
constructor(memorySize) {
this.instances = new FactoryMap(() => new FunctionMemoryStats());
this.counters = new FactoryMap(() => new FunctionMemoryCounters());
this.warned = new Set();
this.memorySize = memorySize || 100;
}
detectedNewLeak(fn, instanceId, memoryUsage) {
if (this.warned.has(fn)) {
return false;
}
const { rss, heapTotal, heapUsed, external } = memoryUsage;
const instanceStats = this.instances.getOrCreate(instanceId);
const counters = this.counters.getOrCreate(instanceId);
if (heapUsed > instanceStats.heapUsed.max) {
counters.heapUsedGrowth++;
}
else {
counters.heapUsedGrowth = 0;
}
if (external > instanceStats.external.max) {
counters.externalGrowth++;
}
else {
counters.externalGrowth = 0;
}
instanceStats.rss.update(rss);
instanceStats.heapTotal.update(heapTotal);
instanceStats.heapUsed.update(heapUsed);
instanceStats.external.update(external);
if (heapUsed > this.memorySize * 0.8 * 2 ** 20 ||
external > this.memorySize * 0.8 * 2 ** 20) {
if (counters.heapUsedGrowth > 4 || counters.externalGrowth > 4) {
this.warned.add(fn);
return true;
}
}
return false;
}
clear() {
this.instances.clear();
this.counters.clear();
this.warned.clear();
}
}
exports.MemoryLeakDetector = MemoryLeakDetector;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWV0cmljcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9tZXRyaWNzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHlDQUEyQztBQUMzQyxxQ0FBaUQ7QUFHakQsTUFBYSxVQUErQixTQUFRLEdBQVM7SUFDekQsWUFBcUIsT0FBc0I7UUFDdkMsS0FBSyxFQUFFLENBQUM7UUFEUyxZQUFPLEdBQVAsT0FBTyxDQUFlO0lBRTNDLENBQUM7SUFFRCxXQUFXLENBQUMsR0FBTTtRQUNkLElBQUksR0FBRyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDeEIsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1lBQ1AsR0FBRyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDeEIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDdkIsQ0FBQztRQUNELE9BQU8sR0FBRyxDQUFDO0lBQ2YsQ0FBQztDQUNKO0FBYkQsZ0NBYUM7QUFFRCxNQUFhLGdCQUFnQjtJQUE3QjtRQUNJLGlCQUFZLEdBQUcsSUFBSSxVQUFVLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSx3QkFBYSxFQUFFLENBQUMsQ0FBQztRQUN6RCxlQUFVLEdBQUcsSUFBSSxVQUFVLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSx3QkFBYSxFQUFFLENBQUMsQ0FBQztRQUN2RCxjQUFTLEdBQUcsSUFBSSx3QkFBYSxFQUFFLENBQUM7SUE4QnBDLENBQUM7SUE1QkcsTUFBTSxDQUNGLEVBQVUsRUFDVixHQUFzRCxFQUN0RCxLQUFhO1FBRWIsSUFBSSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3JELElBQUksQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQyxDQUFD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LElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDdkIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUN0QixJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQ3hCLENBQUM7Q0FDSjtBQWpERCxnREFpREMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBGdW5jdGlvblN0YXRzIH0gZnJvbSBcIi4vcHJvdmlkZXJcIjtcbmltcG9ydCB7IFNtYWxsZXN0TiwgU3RhdGlzdGljcyB9IGZyb20gXCIuL3NoYXJlZFwiO1xuaW1wb3J0IHsgUHJvcGVydGllc09mVHlwZSB9IGZyb20gXCIuL3R5cGVzXCI7XG5cbmV4cG9ydCBjbGFzcyBGYWN0b3J5TWFwPEsgPSBzdHJpbmcsIFYgPSB7fT4gZXh0ZW5kcyBNYXA8SywgVj4ge1xuICAgIGNvbnN0cnVjdG9yKHJlYWRvbmx5IGZhY3Rvcnk6IChrZXk6IEspID0+IFYpIHtcbiAgICAgICAgc3VwZXIoKTtcbiAgICB9XG5cbiAgICBnZXRPckNyZWF0ZShrZXk6IEspIHtcbiAgICAgICAgbGV0IHZhbCA9IHRoaXMuZ2V0KGtleSk7XG4gICAgICAgIGlmICghdmFsKSB7XG4gICAgICAgICAgICB2YWwgPSB0aGlzLmZhY3Rvcnkoa2V5KTtcbiAgICAgICAgICAgIHRoaXMuc2V0KGtleSwgdmFsKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdmFsO1xuICAgIH1cbn1cblxuZXhwb3J0IGNsYXNzIEZ1bmN0aW9uU3RhdHNNYXAge1xuICAgIGZJbmNyZW1lbnRhbCA9IG5ldyBGYWN0b3J5TWFwKCgpID0+IG5ldyBGdW5jdGlvblN0YXRzKCkpO1xuICAgIGZBZ2dyZWdhdGUgPSBuZXcgRmFjdG9yeU1hcCgoKSA9PiBuZXcgRnVuY3Rpb25TdGF0cygpKTtcbiAgICBhZ2dyZWdhdGUgPSBuZXcgRnVuY3Rpb25TdGF0cygpO1xuXG4gICAgdXBkYXRlKFxuICAgICAgICBmbjogc3RyaW5nLFxuICAgICAgICBrZXk6IGtleW9mIFByb3BlcnRpZXNPZlR5cGU8RnVuY3Rpb25TdGF0cywgU3RhdGlzdGljcz4sXG4gICAgICAgIHZhbHVlOiBudW1iZXJcbiAgICApIHtcbiAgICAgICAgdGhpcy5mSW5jcmVtZW50YWwuZ2V0T3JDcmVhdGUoZm4pW2tleV0udXBkYXRlKHZhbHVlKTtcbiAgICAgICAgdGhpcy5mQWdncmVnYXRlLmdldE9yQ3JlYXRlKGZuKVtrZXldLnVwZGF0ZSh2YWx1ZSk7XG4gICAgICAgIHRoaXMuYWdncmVnYXRlW2tleV0udXBkYXRlKHZhbHVlKTtcbiAgICB9XG5cbiAgICBpbmNyKGZuOiBzdHJpbmcsIGtleToga2V5b2YgUHJvcGVydGllc09mVHlwZTxGdW5jdGlvblN0YXRzLCBudW1iZXI+LCBuOiBudW1iZXIgPSAxKSB7XG4gICAgICAgIHRoaXMuZkluY3JlbWVudGFsLmdldE9yQ3JlYXRlKGZuKVtrZXldICs9IG47XG4gICAgICAgIHRoaXMuZkFnZ3JlZ2F0ZS5nZXRPckNyZWF0ZShmbilba2V5XSArPSBuO1xuICAgICAgICB0aGlzLmFnZ3JlZ2F0ZVtrZXldICs9IG47XG4gICAgfVxuXG4gICAgcmVzZXRJbmNyZW1lbnRhbCgpIHtcbiAgICAgICAgdGhpcy5mSW5jcmVtZW50YWwuY2xlYXIoKTtcbiAgICB9XG5cbiAgICB0b1N0cmluZygpIHtcbiAgICAgICAgcmV0dXJuIFsuLi50aGlzLmZBZ2dyZWdhdGVdLm1hcCgoW2tleSwgdmFsdWVdKSA9PiBgWyR7a2V5fV0gJHt2YWx1ZX1gKS5qb2luKFwiXFxuXCIpO1xuICAgIH1cblxuICAgIGNsZWFyKCkge1xuICAgICAgICB0aGlzLmZJbmNyZW1lbnRhbC5jbGVhcigpO1xuICAgICAgICB0aGlzLmZBZ2dyZWdhdGUuY2xlYXIoKTtcbiAgICB9XG59XG5cbmV4cG9ydCBjbGFzcyBGdW5jdGlvbkNwdVVzYWdlIHtcbiAgICB1dGltZSA9IG5ldyBTdGF0aXN0aWNzKCk7XG4gICAgc3RpbWUgPSBuZXcgU3RhdGlzdGljcygpO1xuICAgIGNwdVRpbWUgPSBuZXcgU3RhdGlzdGljcygpO1xuICAgIHNtYWxsZXN0ID0gbmV3IFNtYWxsZXN0TigxMDApO1xufVxuXG5jbGFzcyBGdW5jdGlvbk1lbW9yeVN0YXRzIHtcbiAgICByc3MgPSBuZXcgU3RhdGlzdGljcygpO1xuICAgIGhlYXBUb3RhbCA9IG5ldyBTdGF0aXN0aWNzKCk7XG4gICAgaGVhcFVzZWQgPSBuZXcgU3RhdGlzdGljcygpO1xuICAgIGV4dGVybmFsID0gbmV3IFN0YXRpc3RpY3MoKTtcbn1cblxuY2xhc3MgRnVuY3Rpb25NZW1vcnlDb3VudGVycyB7XG4gICAgaGVhcFVzZWRHcm93dGggPSAwO1xuICAgIGV4dGVybmFsR3Jvd3RoID0gMDtcbn1cblxuZXhwb3J0IGNsYXNzIE1lbW9yeUxlYWtEZXRlY3RvciB7XG4gICAgcHJpdmF0ZSBpbnN0YW5jZXMgPSBuZXcgRmFjdG9yeU1hcCgoKSA9PiBuZXcgRnVuY3Rpb25NZW1vcnlTdGF0cygpKTtcbiAgICBwcml2YXRlIGNvdW50ZXJzID0gbmV3IEZhY3RvcnlNYXAoKCkgPT4gbmV3IEZ1bmN0aW9uTWVtb3J5Q291bnRlcnMoKSk7XG4gICAgcHJpdmF0ZSB3YXJuZWQgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICBwcml2YXRlIG1lbW9yeVNpemU6IG51bWJlcjtcblxuICAgIGNvbnN0cnVjdG9yKG1lbW9yeVNpemU/OiBudW1iZXIpIHtcbiAgICAgICAgdGhpcy5tZW1vcnlTaXplID0gbWVtb3J5U2l6ZSB8fCAxMDA7XG4gICAgfVxuXG4gICAgZGV0ZWN0ZWROZXdMZWFrKGZuOiBzdHJpbmcsIGluc3RhbmNlSWQ6IHN0cmluZywgbWVtb3J5VXNhZ2U6IE5vZGVKUy5NZW1vcnlVc2FnZSkge1xuICAgICAgICBpZiAodGhpcy53YXJuZWQuaGFzKGZuKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHsgcnNzLCBoZWFwVG90YWwsIGhlYXBVc2VkLCBleHRlcm5hbCB9ID0gbWVtb3J5VXNhZ2U7XG4gICAgICAgIGNvbnN0IGluc3RhbmNlU3RhdHMgPSB0aGlzLmluc3RhbmNlcy5nZXRPckNyZWF0ZShpbnN0YW5jZUlkKTtcbiAgICAgICAgY29uc3QgY291bnRlcnMgPSB0aGlzLmNvdW50ZXJzLmdldE9yQ3JlYXRlKGluc3RhbmNlSWQpO1xuICAgICAgICBpZiAoaGVhcFVzZWQgPiBpbnN0YW5jZVN0YXRzLmhlYXBVc2VkLm1heCkge1xuICAgICAgICAgICAgY291bnRlcnMuaGVhcFVzZWRHcm93dGgrKztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvdW50ZXJzLmhlYXBVc2VkR3Jvd3RoID0gMDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZXh0ZXJuYWwgPiBpbnN0YW5jZVN0YXRzLmV4dGVybmFsLm1heCkge1xuICAgICAgICAgICAgY291bnRlcnMuZXh0ZXJuYWxHcm93dGgrKztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvdW50ZXJzLmV4dGVybmFsR3Jvd3RoID0gMDtcbiAgICAgICAgfVxuICAgICAgICBpbnN0YW5jZVN0YXRzLnJzcy51cGRhdGUocnNzKTtcbiAgICAgICAgaW5zdGFuY2VTdGF0cy5oZWFwVG90YWwudXBkYXRlKGhlYXBUb3RhbCk7XG4gICAgICAgIGluc3RhbmNlU3RhdHMuaGVhcFVzZWQudXBkYXRlKGhlYXBVc2VkKTtcbiAgICAgICAgaW5zdGFuY2VTdGF0cy5leHRlcm5hbC51cGRhdGUoZXh0ZXJuYWwpO1xuXG4gICAgICAgIGlmIChcbiAgICAgICAgICAgIGhlYXBVc2VkID4gdGhpcy5tZW1vcnlTaXplICogMC44ICogMiAqKiAyMCB8fFxuICAgICAgICAgICAgZXh0ZXJuYWwgPiB0aGlzLm1lbW9yeVNpemUgKiAwLjggKiAyICoqIDIwXG4gICAgICAgICkge1xuICAgICAgICAgICAgaWYgKGNvdW50ZXJzLmhlYXBVc2VkR3Jvd3RoID4gNCB8fCBjb3VudGVycy5leHRlcm5hbEdyb3d0aCA+IDQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLndhcm5lZC5hZGQoZm4pO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBjbGVhcigpIHtcbiAgICAgICAgdGhpcy5pbnN0YW5jZXMuY2xlYXIoKTtcbiAgICAgICAgdGhpcy5jb3VudGVycy5jbGVhcigpO1xuICAgICAgICB0aGlzLndhcm5lZC5jbGVhcigpO1xuICAgIH1cbn1cbiJdfQ==