mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-01 15:58:28 +01:00
Add performance profiler command (#306548)
* profile * wip * use status bar * clean * clean * clean * chore: add netlog category for network tracing --------- Co-authored-by: deepak1556 <hop2deep@gmail.com>
This commit is contained in:
@@ -242,6 +242,7 @@ export interface ICommonNativeHostService {
|
||||
|
||||
// Perf Introspection
|
||||
profileRenderer(session: string, duration: number): Promise<IV8Profile>;
|
||||
startTracing(categories: string): Promise<void>;
|
||||
|
||||
// Connectivity
|
||||
resolveProxy(url: string): Promise<string | undefined>;
|
||||
|
||||
@@ -1159,11 +1159,29 @@ export class NativeHostMainService extends Disposable implements INativeHostMain
|
||||
}
|
||||
}
|
||||
|
||||
async stopTracing(windowId: number | undefined): Promise<void> {
|
||||
if (!this.environmentMainService.args.trace) {
|
||||
return; // requires tracing to be on
|
||||
private _isTracing = false;
|
||||
|
||||
async startTracing(windowId: number | undefined, categories: string): Promise<void> {
|
||||
if (this._isTracing) {
|
||||
throw new Error(localize('tracing.alreadyInProgress', 'A tracing session is already in progress. Use command `"{0}"` to stop it first.', 'workbench.action.stopTracing'));
|
||||
}
|
||||
|
||||
const traceOptions = ['record-until-full', 'enable-sampling'];
|
||||
|
||||
await contentTracing.startRecording({
|
||||
categoryFilter: categories,
|
||||
traceOptions: traceOptions.join(',')
|
||||
});
|
||||
this._isTracing = true;
|
||||
}
|
||||
|
||||
async stopTracing(windowId: number | undefined): Promise<void> {
|
||||
if (!this._isTracing && !this.environmentMainService.args.trace) {
|
||||
return; // no tracing in progress
|
||||
}
|
||||
|
||||
this._isTracing = false;
|
||||
|
||||
const path = await contentTracing.stopRecording(`${randomPath(this.environmentMainService.userHome.fsPath, this.productService.applicationName)}.trace.txt`);
|
||||
|
||||
// Inform user to report an issue
|
||||
|
||||
@@ -16,9 +16,9 @@ import { KeyCode, KeyMod } from '../../../base/common/keyCodes.js';
|
||||
import { INativeWorkbenchEnvironmentService } from '../../services/environment/electron-browser/environmentService.js';
|
||||
import { URI } from '../../../base/common/uri.js';
|
||||
import { getActiveWindow } from '../../../base/browser/dom.js';
|
||||
import { IDialogService } from '../../../platform/dialogs/common/dialogs.js';
|
||||
import { INativeEnvironmentService } from '../../../platform/environment/common/environment.js';
|
||||
import { IProgressService, ProgressLocation } from '../../../platform/progress/common/progress.js';
|
||||
import { IDialogService } from '../../../platform/dialogs/common/dialogs.js';
|
||||
import { IStatusbarEntryAccessor, IStatusbarService, StatusbarAlignment } from '../../services/statusbar/browser/statusbar.js';
|
||||
|
||||
export class ToggleDevToolsAction extends Action2 {
|
||||
|
||||
@@ -140,6 +140,54 @@ export class ShowContentTracingAction extends Action2 {
|
||||
}
|
||||
}
|
||||
|
||||
let activeTracingEntry: IStatusbarEntryAccessor | undefined;
|
||||
|
||||
export class StartTracing extends Action2 {
|
||||
|
||||
constructor() {
|
||||
super({
|
||||
id: 'workbench.action.startTracing',
|
||||
title: localize2('startTracing', 'Start Tracing'),
|
||||
category: Categories.Developer,
|
||||
f1: true
|
||||
});
|
||||
}
|
||||
|
||||
override async run(accessor: ServicesAccessor): Promise<void> {
|
||||
const nativeHostService = accessor.get(INativeHostService);
|
||||
const statusbarService = accessor.get(IStatusbarService);
|
||||
|
||||
const categories = [
|
||||
'content',
|
||||
'renderer_host',
|
||||
'browser',
|
||||
'renderer',
|
||||
'blink',
|
||||
'blink.user_timing',
|
||||
'netlog',
|
||||
'net',
|
||||
'v8',
|
||||
'disabled-by-default-v8.cpu_profiler',
|
||||
'disabled-by-default-devtools.timeline',
|
||||
'disabled-by-default-network',
|
||||
'disabled-by-default-net',
|
||||
'disabled-by-default-v8.gc_stats',
|
||||
'disabled-by-default-v8.stack_trace',
|
||||
];
|
||||
await nativeHostService.startTracing(categories.join(','));
|
||||
|
||||
activeTracingEntry?.dispose();
|
||||
activeTracingEntry = statusbarService.addEntry({
|
||||
name: localize('startTracing.name', "Performance Trace"),
|
||||
text: '$(record) ' + localize('startTracing.recording', "Recording trace (click to stop)"),
|
||||
ariaLabel: localize('startTracing.ariaLabel', "Recording performance trace. Click to stop recording."),
|
||||
tooltip: localize('startTracing.tooltip', "Click to stop recording"),
|
||||
kind: 'error',
|
||||
command: StopTracing.ID
|
||||
}, 'status.tracing', StatusbarAlignment.LEFT, -Number.MAX_VALUE);
|
||||
}
|
||||
}
|
||||
|
||||
export class StopTracing extends Action2 {
|
||||
|
||||
static readonly ID = 'workbench.action.stopTracing';
|
||||
@@ -154,20 +202,22 @@ export class StopTracing extends Action2 {
|
||||
}
|
||||
|
||||
override async run(accessor: ServicesAccessor): Promise<void> {
|
||||
const environmentService = accessor.get(INativeEnvironmentService);
|
||||
const dialogService = accessor.get(IDialogService);
|
||||
const nativeHostService = accessor.get(INativeHostService);
|
||||
const environmentService = accessor.get(INativeWorkbenchEnvironmentService);
|
||||
const dialogService = accessor.get(IDialogService);
|
||||
const progressService = accessor.get(IProgressService);
|
||||
|
||||
if (!environmentService.args.trace) {
|
||||
if (!activeTracingEntry && !environmentService.args.trace) {
|
||||
const { confirmed } = await dialogService.confirm({
|
||||
message: localize('stopTracing.message', "Tracing requires to launch with a '--trace' argument"),
|
||||
message: localize('stopTracing.message', "No tracing session is in progress. Use 'Developer: Start Tracing' or launch with a '--trace' argument to begin tracing."),
|
||||
primaryButton: localize({ key: 'stopTracing.button', comment: ['&& denotes a mnemonic'] }, "&&Relaunch and Enable Tracing"),
|
||||
});
|
||||
|
||||
if (confirmed) {
|
||||
return nativeHostService.relaunch({ addArgs: ['--trace'] });
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
await progressService.withProgress({
|
||||
@@ -176,5 +226,8 @@ export class StopTracing extends Action2 {
|
||||
cancellable: false,
|
||||
detail: localize('stopTracing.detail', "This can take up to one minute to complete.")
|
||||
}, () => nativeHostService.stopTracing());
|
||||
|
||||
activeTracingEntry?.dispose();
|
||||
activeTracingEntry = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import { MenuRegistry, MenuId, registerAction2 } from '../../platform/actions/co
|
||||
import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from '../../platform/configuration/common/configurationRegistry.js';
|
||||
import { KeyMod, KeyCode } from '../../base/common/keyCodes.js';
|
||||
import { isLinux, isMacintosh, isWindows } from '../../base/common/platform.js';
|
||||
import { ConfigureRuntimeArgumentsAction, ToggleDevToolsAction, ReloadWindowWithExtensionsDisabledAction, OpenUserDataFolderAction, ShowGPUInfoAction, ShowContentTracingAction, StopTracing } from './actions/developerActions.js';
|
||||
import { ConfigureRuntimeArgumentsAction, ToggleDevToolsAction, ReloadWindowWithExtensionsDisabledAction, OpenUserDataFolderAction, ShowGPUInfoAction, ShowContentTracingAction, StopTracing, StartTracing } from './actions/developerActions.js';
|
||||
import { ZoomResetAction, ZoomOutAction, ZoomInAction, CloseWindowAction, SwitchWindowAction, QuickSwitchWindowAction, NewWindowTabHandler, ShowPreviousWindowTabHandler, ShowNextWindowTabHandler, MoveWindowTabToNewWindowHandler, MergeWindowTabsHandlerHandler, ToggleWindowTabsBarHandler, ToggleWindowAlwaysOnTopAction, DisableWindowAlwaysOnTopAction, EnableWindowAlwaysOnTopAction, CloseOtherWindowsAction } from './actions/windowActions.js';
|
||||
import { ContextKeyExpr } from '../../platform/contextkey/common/contextkey.js';
|
||||
import { KeybindingsRegistry, KeybindingWeight } from '../../platform/keybinding/common/keybindingsRegistry.js';
|
||||
@@ -116,6 +116,7 @@ import product from '../../platform/product/common/product.js';
|
||||
registerAction2(ShowGPUInfoAction);
|
||||
registerAction2(ShowContentTracingAction);
|
||||
registerAction2(StopTracing);
|
||||
registerAction2(StartTracing);
|
||||
})();
|
||||
|
||||
// Menu
|
||||
|
||||
@@ -184,6 +184,7 @@ export class TestNativeHostService implements INativeHostService {
|
||||
async windowsGetStringRegKey(hive: 'HKEY_CURRENT_USER' | 'HKEY_LOCAL_MACHINE' | 'HKEY_CLASSES_ROOT' | 'HKEY_USERS' | 'HKEY_CURRENT_CONFIG', path: string, name: string): Promise<string | undefined> { return undefined; }
|
||||
async createZipFile(zipPath: URI, files: { path: string; contents: string }[]): Promise<void> { }
|
||||
async profileRenderer(): Promise<any> { throw new Error(); }
|
||||
async startTracing(): Promise<void> { throw new Error(); }
|
||||
async getScreenshot(rect?: IRectangle): Promise<VSBuffer | undefined> { return undefined; }
|
||||
async showToast(options: IToastOptions): Promise<IToastResult> { return { supported: false, clicked: false }; }
|
||||
async clearToast(id: string): Promise<void> { }
|
||||
|
||||
Reference in New Issue
Block a user