From 2776a40eb4fd4a7231604c9dba17f8423f509b44 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 28 Feb 2017 18:04:06 +0100 Subject: [PATCH] create issue and show profile files --- src/main.js | 4 +- src/vs/base/node/profiler.ts | 6 +-- src/vs/code/electron-main/window.ts | 7 ++- .../environment/common/environment.ts | 3 +- .../environment/node/environmentService.ts | 15 ++++++- src/vs/workbench/electron-browser/actions.ts | 21 +++++---- .../electron-browser/bootstrap/index.js | 2 +- src/vs/workbench/electron-browser/shell.ts | 43 +++++++++++++------ 8 files changed, 71 insertions(+), 30 deletions(-) diff --git a/src/main.js b/src/main.js index 76ba42c53ce..4a36b80358b 100644 --- a/src/main.js +++ b/src/main.js @@ -7,7 +7,9 @@ if (process.argv.indexOf('--performance-startup-profile') >= 0) { var profiler = require('v8-profiler'); - profiler.startProfiling('startup-main', true); + var prefix = require('crypto').randomBytes(2).toString('hex'); + process.env.VSCODE_PROFILES_PREFIX = prefix; + profiler.startProfiling('main', true); } // Perf measurements diff --git a/src/vs/base/node/profiler.ts b/src/vs/base/node/profiler.ts index cbd744bbfe8..6a45ad71d5b 100644 --- a/src/vs/base/node/profiler.ts +++ b/src/vs/base/node/profiler.ts @@ -6,7 +6,6 @@ 'use strict'; import { TPromise } from 'vs/base/common/winjs.base'; -import { homedir } from 'os'; import { join } from 'path'; import { writeFile } from 'vs/base/node/pfs'; @@ -17,7 +16,7 @@ export function startProfiling(name: string): TPromise { }); } -export function stopProfiling(name: string): TPromise { +export function stopProfiling(dir: string, prefix: string): TPromise { return lazyV8Profiler.value.then(profiler => { return profiler.stopProfiling(); }).then(profile => { @@ -28,7 +27,7 @@ export function stopProfiling(name: string): TPromise { reject(error); return; } - const filepath = join(homedir(), `${name}-${Date.now()}.cpuprofile`); + const filepath = join(dir, `${prefix}_${profile.title}.cpuprofile.txt`); writeFile(filepath, result).then(() => resolve(filepath), reject); }); }); @@ -41,6 +40,7 @@ declare interface Profiler { } declare interface Profile { + title: string; export(callback: (err, data) => void); delete(); } diff --git a/src/vs/code/electron-main/window.ts b/src/vs/code/electron-main/window.ts index 33db968e2f0..396e5b4ddc3 100644 --- a/src/vs/code/electron-main/window.ts +++ b/src/vs/code/electron-main/window.ts @@ -468,8 +468,11 @@ export class VSCodeWindow { }, 10000); } - if (this.environmentService.args['performance-startup-profile']) { - stopProfiling('startup-main').then(path => console.log(`cpu profile stored in ${path}`), err => console.error(err)); + // (--performance-startup-profile) save profile to disk + const { performanceStartupProfile } = this.environmentService; + if (performanceStartupProfile) { + stopProfiling(performanceStartupProfile.dir, performanceStartupProfile.prefix) + .done(undefined, err => console.error(err)); } } diff --git a/src/vs/platform/environment/common/environment.ts b/src/vs/platform/environment/common/environment.ts index d61fd525bb9..8e1fd1f9544 100644 --- a/src/vs/platform/environment/common/environment.ts +++ b/src/vs/platform/environment/common/environment.ts @@ -22,7 +22,7 @@ export interface ParsedArgs { locale?: string; 'user-data-dir'?: string; performance?: boolean; - ['performance-startup-profile']?: boolean; + 'performance-startup-profile'?: string; verbose?: boolean; logExtensionHostCommunication?: boolean; 'disable-extensions'?: boolean; @@ -76,6 +76,7 @@ export interface IEnvironmentService { verbose: boolean; wait: boolean; performance: boolean; + performanceStartupProfile: { prefix: string, dir: string } | undefined; mainIPCHandle: string; sharedIPCHandle: string; diff --git a/src/vs/platform/environment/node/environmentService.ts b/src/vs/platform/environment/node/environmentService.ts index b8c47e548ea..7731315961e 100644 --- a/src/vs/platform/environment/node/environmentService.ts +++ b/src/vs/platform/environment/node/environmentService.ts @@ -109,9 +109,22 @@ export class EnvironmentService implements IEnvironmentService { get isBuilt(): boolean { return !process.env['VSCODE_DEV']; } get verbose(): boolean { return this._args.verbose; } get wait(): boolean { return this._args.wait; } - get performance(): boolean { return this._args.performance; } get logExtensionHostCommunication(): boolean { return this._args.logExtensionHostCommunication; } + get performance(): boolean { return this._args.performance; } + + @memoize + get performanceStartupProfile(): { prefix: string, dir: string } | undefined { + if (this._args['performance-startup-profile']) { + return { + prefix: process.env.VSCODE_PROFILES_PREFIX, + dir: os.homedir() + }; + } else { + return undefined; + } + } + @memoize get mainIPCHandle(): string { return getIPCHandle(this.userDataPath, 'main'); } diff --git a/src/vs/workbench/electron-browser/actions.ts b/src/vs/workbench/electron-browser/actions.ts index d0f5483744f..cd4bdb789ac 100644 --- a/src/vs/workbench/electron-browser/actions.ts +++ b/src/vs/workbench/electron-browser/actions.ts @@ -738,9 +738,9 @@ export class ReportPerformanceIssueAction extends Action { super(id, label); } - public run(): TPromise { + public run(appendix?: string): TPromise { return this.integrityService.isPure().then(res => { - const issueUrl = this.generatePerformanceIssueUrl(product.reportIssueUrl, pkg.name, pkg.version, product.commit, product.date, res.isPure); + const issueUrl = this.generatePerformanceIssueUrl(product.reportIssueUrl, pkg.name, pkg.version, product.commit, product.date, res.isPure, appendix); window.open(issueUrl); @@ -748,7 +748,15 @@ export class ReportPerformanceIssueAction extends Action { }); } - private generatePerformanceIssueUrl(baseUrl: string, name: string, version: string, commit: string, date: string, isPure: boolean): string { + private generatePerformanceIssueUrl(baseUrl: string, name: string, version: string, commit: string, date: string, isPure: boolean, appendix?: string): string { + + if (!appendix) { + appendix = `Additional Steps to Reproduce (if any): + +1. +2.`; + } + let nodeModuleLoadTime: number; if (this.environmentService.performance) { nodeModuleLoadTime = this.computeNodeModulesLoadTime(); @@ -775,10 +783,7 @@ ${this.generatePerformanceTable(nodeModuleLoadTime)} --- -Additional Steps to Reproduce (if any): - -1. -2.` +${appendix}` ); return `${baseUrl}${queryStringPrefix}body=${body}`; @@ -899,4 +904,4 @@ export class OpenIntroductoryVideosUrlAction extends Action { window.open(OpenIntroductoryVideosUrlAction.URL); return null; } -} \ No newline at end of file +} diff --git a/src/vs/workbench/electron-browser/bootstrap/index.js b/src/vs/workbench/electron-browser/bootstrap/index.js index c7be3db6a2d..9751c18088a 100644 --- a/src/vs/workbench/electron-browser/bootstrap/index.js +++ b/src/vs/workbench/electron-browser/bootstrap/index.js @@ -9,7 +9,7 @@ if (window.location.search.indexOf('performance-startup-profile') >= 0) { var profiler = require('v8-profiler'); - profiler.startProfiling('startup-renderer', true); + profiler.startProfiling('renderer', true); } /*global window,document,define*/ diff --git a/src/vs/workbench/electron-browser/shell.ts b/src/vs/workbench/electron-browser/shell.ts index f79a3265731..3c0ff844ec8 100644 --- a/src/vs/workbench/electron-browser/shell.ts +++ b/src/vs/workbench/electron-browser/shell.ts @@ -87,7 +87,7 @@ import { URLChannelClient } from 'vs/platform/url/common/urlIpc'; import { IURLService } from 'vs/platform/url/common/url'; import { IBackupService } from 'vs/platform/backup/common/backup'; import { BackupChannelClient } from 'vs/platform/backup/common/backupIpc'; -import { ReloadWindowAction } from 'vs/workbench/electron-browser/actions'; +import { ReloadWindowAction, ReportPerformanceIssueAction } from 'vs/workbench/electron-browser/actions'; import { ExtensionHostProcessWorker } from 'vs/workbench/electron-browser/extensionHost'; import { ITimerService } from 'vs/workbench/services/timer/common/timerService'; import { remote } from 'electron'; @@ -96,6 +96,8 @@ import { MainProcessTextMateSyntax } from 'vs/editor/electron-browser/textMate/T import { BareFontInfo } from 'vs/editor/common/config/fontInfo'; import { readFontInfo } from 'vs/editor/browser/config/configuration'; import SCMPreview from 'vs/workbench/parts/scm/browser/scmPreview'; +import { readdir } from 'vs/base/node/pfs'; +import { join } from 'path'; import 'vs/platform/opener/browser/opener.contribution'; /** @@ -234,21 +236,36 @@ export class WorkbenchShell { } // Profiler: startup cpu profile - if (this.environmentService.args['performance-startup-profile']) { - stopProfiling('startup-renderer').then(path => { - console.log(`cpu profile stored in ${path}`); + const { performanceStartupProfile } = this.environmentService; + if (performanceStartupProfile) { - const restart = this.messageService.confirm({ - type: 'info', - message: nls.localize('prof.message', "Successfully created profiles."), - detail: nls.localize('prof.detail', "To not lose unsaved work, we strongly recommended to restart '{0}' now.", this.environmentService.appNameLong), - primaryButton: nls.localize('prof.restart', "&&Restart") + stopProfiling(performanceStartupProfile.dir, performanceStartupProfile.prefix).then(() => { + + readdir(performanceStartupProfile.dir).then(files => { + return files.filter(value => value.indexOf(performanceStartupProfile.prefix) === 0); + }).then(files => { + + const profileFiles = files.reduce((prev, cur) => `${prev}${join(performanceStartupProfile.dir, cur)}\n`, '\n'); + + const primaryButton = this.messageService.confirm({ + type: 'info', + message: nls.localize('prof.message', "Successfully created profiles."), + detail: nls.localize('prof.detail', "Please create an issue and manually attach the following files:\n{0}", profileFiles), + primaryButton: nls.localize('prof.restartAndFileIssue', "Create Issue and Restart"), + secondaryButton: nls.localize('prof.restart', "Restart") + }); + + let createIssue = TPromise.as(undefined); + if (primaryButton) { + const action = this.workbench.getInstantiationService().createInstance(ReportPerformanceIssueAction, ReportPerformanceIssueAction.ID, ReportPerformanceIssueAction.LABEL); + + createIssue = action.run(`:warning: Make sure to **attach** these files: :warning:\n${files.map(file => `-\`${join(performanceStartupProfile.dir, file)}\``).join('\n')}`).then(() => { + return this.windowsService.showItemInFolder(performanceStartupProfile.dir); + }); + } + createIssue.then(() => this.windowsService.relaunch({ removeArgs: ['--performance-startup-profile'] })); }); - if (restart) { - this.windowsService.relaunch({ removeArgs: ['--performance-startup-profile'] }); - } - }, err => console.error(err)); } }