UNPKG

@acromedia/sloth

Version:

Resource profiler for node, utilizing child processes

97 lines (96 loc) 3.4 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const child_process_1 = __importDefault(require("child_process")); const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); const ProfileResults_1 = __importDefault(require("./ProfileResults")); class Profiler { /** * Class for profiling a process, provided a PID. * * @param {Number} pid * The process PID. * * @param {Object} opts * Profiler options. * * @param {Boolean=} opts.toFile * Whether to spit out the output into a JSON file. * * @param {Number=} opts.timestep * The amount of time in milliseconds before each memory check. * * @param {Number=} opts.waitAfterEnd * The amount of time to wait after the profiler has been stopped. * * @param {Boolean=} opts.trimNodeProcessUsage * Trim base node process usage from tracked usage. */ constructor(pid, opts = {}) { this.toWatch = pid; this.results = null; this.process = null; if (opts && typeof opts !== 'object') throw new Error('Provided options was not an object.'); // Optional params this.toFile = opts.toFile || false; this.timestep = opts.timestep || 100; this.wait = opts.waitAfterEnd || 0; this.trimNodeProcessUsage = opts.trimNodeProcessUsage || true; } /** * Starts the watching process by spawning a fork of the monitoring file. */ async start() { let execArgv = []; let procPath = path_1.default.join(__dirname, '../helpers/watch.js'); if (!fs_1.default.existsSync(procPath)) { procPath = procPath.replace('.js', '.ts'); execArgv = ['-r', 'ts-node/register']; } this.process = child_process_1.default.fork(procPath, [ this.toWatch, this.timestep, this.wait, this.toFile, this.trimNodeProcessUsage, ], { execArgv, }); // Setup our message handler for when the process sends the data. this.process.on('message', (message) => { this.results = message; // Kill the watcher process (if it hasn't already). if (this.process) this.process.kill(); this.process = null; }); // Ensure process can get an accurate baseline by waiting a few cycles before beginning. return new Promise((resolve) => { setTimeout(() => { resolve(this); }, this.timestep * 3); }); } /** * Kills the monitoring fork process, returns data. */ end() { // Send 'stop' message which will give us our data. // Once we have the data, we can safely kill the process. if (this.process) this.process.send('stop'); return new Promise((resolve) => { const intr = setInterval(() => { if (!this.process) { clearInterval(intr); resolve(new ProfileResults_1.default(this.results)); } }, 100); }); } } exports.default = Profiler;