Skip to content

Commit

Permalink
perf - better distinguish main.js load and run timers (#230998)
Browse files Browse the repository at this point in the history
  • Loading branch information
bpasero authored Oct 10, 2024
1 parent 490dc3d commit 8bc93a5
Show file tree
Hide file tree
Showing 7 changed files with 31 additions and 12 deletions.
2 changes: 1 addition & 1 deletion src/bootstrap-esm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ if (process.env['ELECTRON_RUN_AS_NODE'] || process.versions['electron']) {
globalThis._VSCODE_PRODUCT_JSON = { ...product };
if (process.env['VSCODE_DEV']) {
try {
const overrides = require('../product.overrides.json');
const overrides: unknown = require('../product.overrides.json');
globalThis._VSCODE_PRODUCT_JSON = Object.assign(globalThis._VSCODE_PRODUCT_JSON, overrides);
} catch (error) { /* ignore */ }
}
Expand Down
4 changes: 2 additions & 2 deletions src/bootstrap-fork.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ function pipeLoggingToParent(): void {
* Prevent circular stringify and convert arguments to real array
*/
function safeToString(args: ArrayLike<unknown>): string {
const seen: string[] = [];
const seen: unknown[] = [];
const argsArray: unknown[] = [];

// Massage some arguments with special treatment
Expand Down Expand Up @@ -50,7 +50,7 @@ function pipeLoggingToParent(): void {
}

try {
const res = JSON.stringify(argsArray, function (key, value) {
const res = JSON.stringify(argsArray, function (key, value: unknown) {

// Objects get special treatment to prevent circles
if (isObject(value) || Array.isArray(value)) {
Expand Down
12 changes: 10 additions & 2 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import * as path from 'path';
import * as fs from 'original-fs';
import * as os from 'os';
import { performance } from 'perf_hooks';
import { configurePortable } from './bootstrap-node.js';
import { bootstrapESM } from './bootstrap-esm.js';
import { fileURLToPath } from 'url';
Expand All @@ -24,6 +25,14 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url));

perf.mark('code/didStartMain');

perf.mark('code/willLoadMainBundle', {
// When built, the main bundle is a single JS file with all
// dependencies inlined. As such, we mark `willLoadMainBundle`
// as the start of the main bundle loading process.
startTime: Math.floor(performance.timeOrigin)
});
perf.mark('code/didLoadMainBundle');

// Enable portable support
const portable = configurePortable(product);

Expand Down Expand Up @@ -177,9 +186,8 @@ async function startup(codeCachePath: string | undefined, nlsConfig: INLSConfigu
await bootstrapESM();

// Load Main
perf.mark('code/willLoadMainBundle');
await import('./vs/code/electron-main/main.js');
perf.mark('code/didLoadMainBundle');
perf.mark('code/didRunMainBundle');
}

function configureCommandlineSwitchesSync(cliArgs: NativeParsedArgs) {
Expand Down
10 changes: 5 additions & 5 deletions src/vs/base/common/performance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ function _definePolyfillMarks(timeOrigin?: number) {
_data.push('code/timeOrigin', timeOrigin);
}

function mark(name: string) {
_data.push(name, Date.now());
function mark(name: string, markOptions?: { startTime?: number }) {
_data.push(name, markOptions?.startTime ?? Date.now());
}
function getMarks() {
const result = [];
Expand Down Expand Up @@ -45,8 +45,8 @@ function _define() {
} else {
// use "native" performance for mark and getMarks
return {
mark(name: string) {
performance.mark(name);
mark(name: string, markOptions?: { startTime?: number }) {
performance.mark(name, markOptions);
},
getMarks() {
let timeOrigin = performance.timeOrigin;
Expand Down Expand Up @@ -89,7 +89,7 @@ function _factory(sharedObj: any) {

const perf = _factory(globalThis);

export const mark: (name: string) => void = perf.mark;
export const mark: (name: string, markOptions?: { startTime?: number }) => void = perf.mark;

export interface PerformanceMark {
readonly name: string;
Expand Down
2 changes: 1 addition & 1 deletion src/vs/code/node/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ export async function main(argv: string[]): Promise<any> {
let source: string | undefined;
let target: string | undefined;
try {
const argsContents = JSON.parse(readFileSync(argsFile, 'utf8'));
const argsContents: { source: string; target: string } = JSON.parse(readFileSync(argsFile, 'utf8'));
source = argsContents.source;
target = argsContents.target;
} catch (error) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,8 @@ class PerfModelContentProvider implements ITextModelContentProvider {
const table: Array<Array<string | number | undefined>> = [];
table.push(['start => app.isReady', metrics.timers.ellapsedAppReady, '[main]', `initial startup: ${metrics.initialStartup}`]);
table.push(['nls:start => nls:end', metrics.timers.ellapsedNlsGeneration, '[main]', `initial startup: ${metrics.initialStartup}`]);
table.push(['import(main.bundle.js)', metrics.timers.ellapsedLoadMainBundle, '[main]', `initial startup: ${metrics.initialStartup}`]);
table.push(['import(main.js)', metrics.timers.ellapsedLoadMainBundle, '[main]', `initial startup: ${metrics.initialStartup}`]);
table.push(['run main.js', metrics.timers.ellapsedRunMainBundle, '[main]', `initial startup: ${metrics.initialStartup}`]);
table.push(['start crash reporter', metrics.timers.ellapsedCrashReporter, '[main]', `initial startup: ${metrics.initialStartup}`]);
table.push(['serve main IPC handle', metrics.timers.ellapsedMainServer, '[main]', `initial startup: ${metrics.initialStartup}`]);
table.push(['create window', metrics.timers.ellapsedWindowCreate, '[main]', `initial startup: ${metrics.initialStartup}, ${metrics.initialStartup ? `state: ${metrics.timers.ellapsedWindowRestoreState}ms, widget: ${metrics.timers.ellapsedBrowserWindowCreate}ms, show: ${metrics.timers.ellapsedWindowMaximize}ms` : ''}`]);
Expand Down
10 changes: 10 additions & 0 deletions src/vs/workbench/services/timer/browser/timerService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export interface IMemoryInfo {
"timers.ellapsedAppReady" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true },
"timers.ellapsedNlsGeneration" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true },
"timers.ellapsedLoadMainBundle" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true },
"timers.ellapsedRunMainBundle" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true },
"timers.ellapsedCrashReporter" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true },
"timers.ellapsedMainServer" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true },
"timers.ellapsedWindowCreate" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true },
Expand Down Expand Up @@ -188,6 +189,14 @@ export interface IStartupMetrics {
*/
readonly ellapsedLoadMainBundle?: number;

/**
* The time it took to run the main bundle.
*
* * Happens in the main-process
* * Measured with the `didStartMain` and `didRunMainBundle` performance marks.
*/
readonly ellapsedRunMainBundle?: number;

/**
* The time it took to start the crash reporter.
*
Expand Down Expand Up @@ -692,6 +701,7 @@ export abstract class AbstractTimerService implements ITimerService {
ellapsedAppReady: initialStartup ? this._marks.getDuration('code/didStartMain', 'code/mainAppReady') : undefined,
ellapsedNlsGeneration: initialStartup ? this._marks.getDuration('code/willGenerateNls', 'code/didGenerateNls') : undefined,
ellapsedLoadMainBundle: initialStartup ? this._marks.getDuration('code/willLoadMainBundle', 'code/didLoadMainBundle') : undefined,
ellapsedRunMainBundle: initialStartup ? this._marks.getDuration('code/didStartMain', 'code/didRunMainBundle') : undefined,
ellapsedCrashReporter: initialStartup ? this._marks.getDuration('code/willStartCrashReporter', 'code/didStartCrashReporter') : undefined,
ellapsedMainServer: initialStartup ? this._marks.getDuration('code/willStartMainServer', 'code/didStartMainServer') : undefined,
ellapsedWindowCreate: initialStartup ? this._marks.getDuration('code/willCreateCodeWindow', 'code/didCreateCodeWindow') : undefined,
Expand Down

0 comments on commit 8bc93a5

Please sign in to comment.