create issue and show profile files

This commit is contained in:
Johannes Rieken 2017-02-28 18:04:06 +01:00
parent a050410a77
commit 2776a40eb4
8 changed files with 71 additions and 30 deletions

View file

@ -7,7 +7,9 @@
if (process.argv.indexOf('--performance-startup-profile') >= 0) { if (process.argv.indexOf('--performance-startup-profile') >= 0) {
var profiler = require('v8-profiler'); 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 // Perf measurements

View file

@ -6,7 +6,6 @@
'use strict'; 'use strict';
import { TPromise } from 'vs/base/common/winjs.base'; import { TPromise } from 'vs/base/common/winjs.base';
import { homedir } from 'os';
import { join } from 'path'; import { join } from 'path';
import { writeFile } from 'vs/base/node/pfs'; import { writeFile } from 'vs/base/node/pfs';
@ -17,7 +16,7 @@ export function startProfiling(name: string): TPromise<boolean> {
}); });
} }
export function stopProfiling(name: string): TPromise<string> { export function stopProfiling(dir: string, prefix: string): TPromise<string> {
return lazyV8Profiler.value.then(profiler => { return lazyV8Profiler.value.then(profiler => {
return profiler.stopProfiling(); return profiler.stopProfiling();
}).then(profile => { }).then(profile => {
@ -28,7 +27,7 @@ export function stopProfiling(name: string): TPromise<string> {
reject(error); reject(error);
return; 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); writeFile(filepath, result).then(() => resolve(filepath), reject);
}); });
}); });
@ -41,6 +40,7 @@ declare interface Profiler {
} }
declare interface Profile { declare interface Profile {
title: string;
export(callback: (err, data) => void); export(callback: (err, data) => void);
delete(); delete();
} }

View file

@ -468,8 +468,11 @@ export class VSCodeWindow {
}, 10000); }, 10000);
} }
if (this.environmentService.args['performance-startup-profile']) { // (--performance-startup-profile) save profile to disk
stopProfiling('startup-main').then(path => console.log(`cpu profile stored in ${path}`), err => console.error(err)); const { performanceStartupProfile } = this.environmentService;
if (performanceStartupProfile) {
stopProfiling(performanceStartupProfile.dir, performanceStartupProfile.prefix)
.done(undefined, err => console.error(err));
} }
} }

View file

@ -22,7 +22,7 @@ export interface ParsedArgs {
locale?: string; locale?: string;
'user-data-dir'?: string; 'user-data-dir'?: string;
performance?: boolean; performance?: boolean;
['performance-startup-profile']?: boolean; 'performance-startup-profile'?: string;
verbose?: boolean; verbose?: boolean;
logExtensionHostCommunication?: boolean; logExtensionHostCommunication?: boolean;
'disable-extensions'?: boolean; 'disable-extensions'?: boolean;
@ -76,6 +76,7 @@ export interface IEnvironmentService {
verbose: boolean; verbose: boolean;
wait: boolean; wait: boolean;
performance: boolean; performance: boolean;
performanceStartupProfile: { prefix: string, dir: string } | undefined;
mainIPCHandle: string; mainIPCHandle: string;
sharedIPCHandle: string; sharedIPCHandle: string;

View file

@ -109,9 +109,22 @@ export class EnvironmentService implements IEnvironmentService {
get isBuilt(): boolean { return !process.env['VSCODE_DEV']; } get isBuilt(): boolean { return !process.env['VSCODE_DEV']; }
get verbose(): boolean { return this._args.verbose; } get verbose(): boolean { return this._args.verbose; }
get wait(): boolean { return this._args.wait; } get wait(): boolean { return this._args.wait; }
get performance(): boolean { return this._args.performance; }
get logExtensionHostCommunication(): boolean { return this._args.logExtensionHostCommunication; } 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 @memoize
get mainIPCHandle(): string { return getIPCHandle(this.userDataPath, 'main'); } get mainIPCHandle(): string { return getIPCHandle(this.userDataPath, 'main'); }

View file

@ -738,9 +738,9 @@ export class ReportPerformanceIssueAction extends Action {
super(id, label); super(id, label);
} }
public run(): TPromise<boolean> { public run(appendix?: string): TPromise<boolean> {
return this.integrityService.isPure().then(res => { 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); 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; let nodeModuleLoadTime: number;
if (this.environmentService.performance) { if (this.environmentService.performance) {
nodeModuleLoadTime = this.computeNodeModulesLoadTime(); nodeModuleLoadTime = this.computeNodeModulesLoadTime();
@ -775,10 +783,7 @@ ${this.generatePerformanceTable(nodeModuleLoadTime)}
--- ---
Additional Steps to Reproduce (if any): ${appendix}`
1.
2.`
); );
return `${baseUrl}${queryStringPrefix}body=${body}`; return `${baseUrl}${queryStringPrefix}body=${body}`;
@ -899,4 +904,4 @@ export class OpenIntroductoryVideosUrlAction extends Action {
window.open(OpenIntroductoryVideosUrlAction.URL); window.open(OpenIntroductoryVideosUrlAction.URL);
return null; return null;
} }
} }

View file

@ -9,7 +9,7 @@
if (window.location.search.indexOf('performance-startup-profile') >= 0) { if (window.location.search.indexOf('performance-startup-profile') >= 0) {
var profiler = require('v8-profiler'); var profiler = require('v8-profiler');
profiler.startProfiling('startup-renderer', true); profiler.startProfiling('renderer', true);
} }
/*global window,document,define*/ /*global window,document,define*/

View file

@ -87,7 +87,7 @@ import { URLChannelClient } from 'vs/platform/url/common/urlIpc';
import { IURLService } from 'vs/platform/url/common/url'; import { IURLService } from 'vs/platform/url/common/url';
import { IBackupService } from 'vs/platform/backup/common/backup'; import { IBackupService } from 'vs/platform/backup/common/backup';
import { BackupChannelClient } from 'vs/platform/backup/common/backupIpc'; 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 { ExtensionHostProcessWorker } from 'vs/workbench/electron-browser/extensionHost';
import { ITimerService } from 'vs/workbench/services/timer/common/timerService'; import { ITimerService } from 'vs/workbench/services/timer/common/timerService';
import { remote } from 'electron'; 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 { BareFontInfo } from 'vs/editor/common/config/fontInfo';
import { readFontInfo } from 'vs/editor/browser/config/configuration'; import { readFontInfo } from 'vs/editor/browser/config/configuration';
import SCMPreview from 'vs/workbench/parts/scm/browser/scmPreview'; 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'; import 'vs/platform/opener/browser/opener.contribution';
/** /**
@ -234,21 +236,36 @@ export class WorkbenchShell {
} }
// Profiler: startup cpu profile // Profiler: startup cpu profile
if (this.environmentService.args['performance-startup-profile']) { const { performanceStartupProfile } = this.environmentService;
stopProfiling('startup-renderer').then(path => { if (performanceStartupProfile) {
console.log(`cpu profile stored in ${path}`);
const restart = this.messageService.confirm({ stopProfiling(performanceStartupProfile.dir, performanceStartupProfile.prefix).then(() => {
type: 'info',
message: nls.localize('prof.message', "Successfully created profiles."), readdir(performanceStartupProfile.dir).then(files => {
detail: nls.localize('prof.detail', "To not lose unsaved work, we strongly recommended to restart '{0}' now.", this.environmentService.appNameLong), return files.filter(value => value.indexOf(performanceStartupProfile.prefix) === 0);
primaryButton: nls.localize('prof.restart', "&&Restart") }).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)); }, err => console.error(err));
} }
} }