diff --git a/packages/api/schema/stryker-core.json b/packages/api/schema/stryker-core.json index dc43cc3657..7ce5117563 100644 --- a/packages/api/schema/stryker-core.json +++ b/packages/api/schema/stryker-core.json @@ -414,6 +414,11 @@ } ], "description": "Enable or disable certain warnings" + }, + "cpuProf": { + "description": "TODO: Describe", + "default": false, + "type": "boolean" } } } diff --git a/packages/core/src/StrykerCli.ts b/packages/core/src/StrykerCli.ts index 32639c5232..37c62fcb3e 100644 --- a/packages/core/src/StrykerCli.ts +++ b/packages/core/src/StrykerCli.ts @@ -57,6 +57,7 @@ export default class StrykerCli { this.command = cmd; this.strykerConfig = config; }) + .option('--cpu-prof', 'TODO: Write description. Note that this will not profile the main process!') .option( '-f, --files ', 'A comma separated list of globbing expression used for selecting all files needed to run the tests. For a more detailed way of selecting input files, please use a configFile. Example: node_modules/a-lib/**/*.js,src/**/*.js,!src/index.js,a.js,test/**/*.js', diff --git a/packages/core/src/child-proxy/ChildProcessProxy.ts b/packages/core/src/child-proxy/ChildProcessProxy.ts index e22453616e..ac6285d54a 100644 --- a/packages/core/src/child-proxy/ChildProcessProxy.ts +++ b/packages/core/src/child-proxy/ChildProcessProxy.ts @@ -27,6 +27,7 @@ const BROKEN_PIPE_ERROR_CODE = 'EPIPE'; const IPC_CHANNEL_CLOSED_ERROR_CODE = 'ERR_IPC_CHANNEL_CLOSED'; const TIMEOUT_FOR_DISPOSE = 2000; +let n = 0; export default class ChildProcessProxy implements Disposable { public readonly proxy: Promisified; @@ -48,7 +49,14 @@ export default class ChildProcessProxy implements Disposable { additionalInjectableValues: unknown, workingDirectory: string ) { - this.worker = fork(require.resolve('./ChildProcessProxyWorker'), [autoStart], { silent: true, execArgv: [] }); + const execArgv = []; + if (options.cpuProf) { + execArgv.push('--cpu-prof'); + execArgv.push(`--cpu-prof-name=child-process-${n}.cpuprofile`); + n++; + } + + this.worker = fork(require.resolve('./ChildProcessProxyWorker'), [autoStart], { silent: true, execArgv: execArgv }); this.initTask = new Task(); this.log.debug('Starting %s in child process %s', requirePath, this.worker.pid); this.send({ diff --git a/packages/core/src/child-proxy/ChildProcessProxyWorker.ts b/packages/core/src/child-proxy/ChildProcessProxyWorker.ts index 32a8988f68..417b7ef9b8 100644 --- a/packages/core/src/child-proxy/ChildProcessProxyWorker.ts +++ b/packages/core/src/child-proxy/ChildProcessProxyWorker.ts @@ -42,7 +42,11 @@ export default class ChildProcessProxyWorker { const sendCompleted = () => { this.send({ kind: ParentMessageKind.DisposeCompleted }); }; - LogConfigurator.shutdown().then(sendCompleted).catch(sendCompleted); + LogConfigurator.shutdown() + .then(sendCompleted) + .catch(sendCompleted) + // Exit gracefully so we can generate CPU profiles for these processes. + .finally(() => process.exit(0)); break; } }