diff --git a/src/vs/code/node/cli.ts b/src/vs/code/node/cli.ts index 94b66896ed0..fc424f37727 100644 --- a/src/vs/code/node/cli.ts +++ b/src/vs/code/node/cli.ts @@ -19,6 +19,7 @@ import { resolveTerminalEncoding } from 'vs/base/node/encoding'; import * as iconv from 'iconv-lite'; import { writeFileAndFlushSync } from 'vs/base/node/extfs'; import { isWindows } from 'vs/base/common/platform'; +import { ProfilingSession } from 'v8-inspect-profiler'; function shouldSpawnCliProcess(argv: ParsedArgs): boolean { return !!argv['install-source'] @@ -271,37 +272,54 @@ export async function main(argv: string[]): Promise { fs.writeFileSync(filenamePrefix, argv.slice(-6).join('|')); processCallbacks.push(async _child => { + + class Profiler { + static async start(name: string, filenamePrefix: string, opts: { port: number, tries?: number }) { + const profiler = await import('v8-inspect-profiler'); + + let session: ProfilingSession; + try { + session = await profiler.startProfiling(opts); + } catch (err) { + console.error(`FAILED to start profiling for '${name}' on port '${opts.port}'`); + } + + return { + async stop() { + if (!session) { + return; + } + let suffix = ''; + let profile = await session.stop(); + if (!process.env['VSCODE_DEV']) { + // when running from a not-development-build we remove + // absolute filenames because we don't want to reveal anything + // about users. We also append the `.txt` suffix to make it + // easier to attach these files to GH issues + profile = profiler.rewriteAbsolutePaths(profile, 'piiRemoved'); + suffix = '.txt'; + } + + await profiler.writeProfile(profile, `${filenamePrefix}-${name}.cpuprofile${suffix}`); + } + }; + } + } + try { // load and start profiler - const profiler = await import('v8-inspect-profiler'); - const main = await profiler.startProfiling({ port: portMain }); - const renderer = await profiler.startProfiling({ port: portRenderer, tries: 200 }); - const extHost = await profiler.startProfiling({ port: portExthost, tries: 300 }); + const main = await Profiler.start('main', filenamePrefix, { port: portMain }); + const renderer = await Profiler.start('renderer', filenamePrefix, { port: portRenderer, tries: 200 }); + const extHost = await Profiler.start('extHost', filenamePrefix, { port: portExthost, tries: 300 }); // wait for the renderer to delete the // marker file await whenDeleted(filenamePrefix); - let profileMain = await main.stop(); - let profileRenderer = await renderer.stop(); - let profileExtHost = await extHost.stop(); - let suffix = ''; - - if (!process.env['VSCODE_DEV']) { - // when running from a not-development-build we remove - // absolute filenames because we don't want to reveal anything - // about users. We also append the `.txt` suffix to make it - // easier to attach these files to GH issues - profileMain = profiler.rewriteAbsolutePaths(profileMain, 'piiRemoved'); - profileRenderer = profiler.rewriteAbsolutePaths(profileRenderer, 'piiRemoved'); - profileExtHost = profiler.rewriteAbsolutePaths(profileExtHost, 'piiRemoved'); - suffix = '.txt'; - } - - // finally stop profiling and save profiles to disk - await profiler.writeProfile(profileMain, `${filenamePrefix}-main.cpuprofile${suffix}`); - await profiler.writeProfile(profileRenderer, `${filenamePrefix}-renderer.cpuprofile${suffix}`); - await profiler.writeProfile(profileExtHost, `${filenamePrefix}-exthost.cpuprofile${suffix}`); + // stop profiling + await main.stop(); + await renderer.stop(); + await extHost.stop(); // re-create the marker file to signal that profiling is done fs.writeFileSync(filenamePrefix, '');