Skip to content

Commit

Permalink
exthost: fix profiling not working (#209142)
Browse files Browse the repository at this point in the history
* exthost: fix profiling not working

Fixes #194678. Requires jrieken/v8-inspect-profiler#3 to be merged and published in order to pass the 'host' down.

* bump package
  • Loading branch information
connor4312 committed Apr 2, 2024
1 parent e2d3f25 commit 7a523c2
Show file tree
Hide file tree
Showing 17 changed files with 55 additions and 52 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@
"native-watchdog": "^1.4.1",
"node-pty": "1.1.0-beta11",
"tas-client-umd": "0.1.8",
"v8-inspect-profiler": "^0.1.0",
"v8-inspect-profiler": "^0.1.1",
"vscode-oniguruma": "1.7.0",
"vscode-regexpp": "^3.1.0",
"vscode-textmate": "9.0.0",
Expand Down
9 changes: 5 additions & 4 deletions src/vs/code/node/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,7 @@ export async function main(argv: string[]): Promise<any> {
// to get better profile traces. Last, we listen on stdout for a signal that tells us to
// stop profiling.
if (args['prof-startup']) {
const profileHost = '127.0.0.1';
const portMain = await findFreePort(randomPort(), 10, 3000);
const portRenderer = await findFreePort(portMain + 1, 10, 3000);
const portExthost = await findFreePort(portRenderer + 1, 10, 3000);
Expand All @@ -335,9 +336,9 @@ export async function main(argv: string[]): Promise<any> {

const filenamePrefix = randomPath(homedir(), 'prof');

addArg(argv, `--inspect-brk=${portMain}`);
addArg(argv, `--remote-debugging-port=${portRenderer}`);
addArg(argv, `--inspect-brk-extensions=${portExthost}`);
addArg(argv, `--inspect-brk=${profileHost}:${portMain}`);
addArg(argv, `--remote-debugging-port=${profileHost}:${portRenderer}`);
addArg(argv, `--inspect-brk-extensions=${profileHost}:${portExthost}`);
addArg(argv, `--prof-startup-prefix`, filenamePrefix);
addArg(argv, `--no-cached-data`);

Expand All @@ -351,7 +352,7 @@ export async function main(argv: string[]): Promise<any> {

let session: ProfilingSession;
try {
session = await profiler.startProfiling(opts);
session = await profiler.startProfiling({ ...opts, host: profileHost });
} catch (err) {
console.error(`FAILED to start profiling for '${name}' on port '${opts.port}'`);
}
Expand Down
2 changes: 1 addition & 1 deletion src/vs/platform/profiling/common/profiling.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export interface IV8InspectProfilingService {

_serviceBrand: undefined;

startProfiling(options: { port: number }): Promise<string>;
startProfiling(options: { host: string; port: number }): Promise<string>;

stopProfiling(sessionId: string): Promise<IV8Profile>;
}
Expand Down
4 changes: 2 additions & 2 deletions src/vs/platform/profiling/node/profilingService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ export class InspectProfilingService implements IV8InspectProfilingService {

private readonly _sessions = new Map<string, ProfilingSession>();

async startProfiling(options: { port: number }): Promise<string> {
async startProfiling(options: { host: string; port: number }): Promise<string> {
const prof = await import('v8-inspect-profiler');
const session = await prof.startProfiling({ port: options.port, checkForPaused: true });
const session = await prof.startProfiling({ host: options.host, port: options.port, checkForPaused: true });
const id = generateUuid();
this._sessions.set(id, session);
return id;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export class DebugExtensionHostAction extends Action {
type: 'node',
name: nls.localize('debugExtensionHost.launch.name', "Attach Extension Host"),
request: 'attach',
port: inspectPorts[0]
port: inspectPorts[0].port,
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ export class ExtensionHostProfileService extends Disposable implements IExtensio

this._setState(ProfileSessionState.Starting);

return this._instantiationService.createInstance(ExtensionHostProfiler, inspectPorts[0]).start().then((value) => {
return this._instantiationService.createInstance(ExtensionHostProfiler, inspectPorts[0].host, inspectPorts[0].port).start().then((value) => {
this._profileSession = value;
this._setState(ProfileSessionState.Running);
}, (err) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,9 @@ export class ExtensionsAutoProfiler implements IWorkbenchContribution {
return;
}

const port = await event.getInspectPort(true);
const listener = await event.getInspectListener(true);

if (!port) {
if (!listener) {
return;
}

Expand All @@ -95,7 +95,7 @@ export class ExtensionsAutoProfiler implements IWorkbenchContribution {

let session: ProfileSession;
try {
session = await this._instantiationService.createInstance(ExtensionHostProfiler, port).start();
session = await this._instantiationService.createInstance(ExtensionHostProfiler, listener.host, listener.port).start();

} catch (err) {
this._session = undefined;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ export class WebWorkerExtensionHost extends Disposable implements IExtensionHost
super.dispose();
}

getInspectPort(): number | undefined {
getInspectPort(): undefined {
return undefined;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import * as perf from 'vs/base/common/performance';
import { isCI } from 'vs/base/common/platform';
import { isEqualOrParent } from 'vs/base/common/resources';
import { StopWatch } from 'vs/base/common/stopwatch';
import { isDefined } from 'vs/base/common/types';
import { URI } from 'vs/base/common/uri';
import * as nls from 'vs/nls';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
Expand Down Expand Up @@ -767,7 +768,7 @@ export abstract class AbstractExtensionService extends Disposable implements IEx
this._onDidChangeResponsiveChange.fire({
extensionHostKind: processManager.kind,
isResponsive: responsiveState === ResponsiveState.Responsive,
getInspectPort: (tryEnableInspector: boolean) => {
getInspectListener: (tryEnableInspector: boolean) => {
return processManager.getInspectPort(tryEnableInspector);
}
});
Expand Down Expand Up @@ -1001,12 +1002,12 @@ export abstract class AbstractExtensionService extends Disposable implements IEx
return result;
}

public async getInspectPorts(extensionHostKind: ExtensionHostKind, tryEnableInspector: boolean): Promise<number[]> {
public async getInspectPorts(extensionHostKind: ExtensionHostKind, tryEnableInspector: boolean): Promise<{ port: number; host: string }[]> {
const result = await Promise.all(
this._getExtensionHostManagers(extensionHostKind).map(extHost => extHost.getInspectPort(tryEnableInspector))
);
// remove 0s:
return result.filter(element => Boolean(element));
return result.filter(isDefined);
}

public async setRemoteEnvironment(env: { [key: string]: string | null }): Promise<void> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ export class ExtensionHostManager extends Disposable implements IExtensionHostMa
this._resolvedActivationEvents.add(activationEvent);
}

public async getInspectPort(tryEnableInspector: boolean): Promise<number> {
public async getInspectPort(tryEnableInspector: boolean): Promise<{ port: number; host: string } | undefined> {
if (this._extensionHost) {
if (tryEnableInspector) {
await this._extensionHost.enableInspectPort();
Expand All @@ -364,7 +364,8 @@ export class ExtensionHostManager extends Disposable implements IExtensionHostMa
return port;
}
}
return 0;

return undefined;
}

public async resolveAuthority(remoteAuthority: string, resolveAttempt: number): Promise<IResolveAuthorityResult> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export interface IExtensionHostManager {
activate(extension: ExtensionIdentifier, reason: ExtensionActivationReason): Promise<boolean>;
activateByEvent(activationEvent: string, activationKind: ActivationKind): Promise<void>;
activationEventIsDone(activationEvent: string): boolean;
getInspectPort(tryEnableInspector: boolean): Promise<number>;
getInspectPort(tryEnableInspector: boolean): Promise<{ port: number; host: string } | undefined>;
resolveAuthority(remoteAuthority: string, resolveAttempt: number): Promise<IResolveAuthorityResult>;
/**
* Returns `null` if no resolver for `remoteAuthority` is found.
Expand Down
8 changes: 4 additions & 4 deletions src/vs/workbench/services/extensions/common/extensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ export interface IExtensionHost {
readonly onExit: Event<[number, string | null]>;

start(): Promise<IMessagePassingProtocol>;
getInspectPort(): number | undefined;
getInspectPort(): { port: number; host: string } | undefined;
enableInspectPort(): Promise<boolean>;
dispose(): void;
}
Expand Down Expand Up @@ -367,7 +367,7 @@ export interface IResponsiveStateChangeEvent {
/**
* Return the inspect port or `0`. `0` means inspection is not possible.
*/
getInspectPort(tryEnableInspector: boolean): Promise<number>;
getInspectListener(tryEnableInspector: boolean): Promise<{ port: number; host: string } | undefined>;
}

export const enum ActivationKind {
Expand Down Expand Up @@ -505,7 +505,7 @@ export interface IExtensionService {
/**
* Return the inspect ports (if inspection is possible) for extension hosts of kind `extensionHostKind`.
*/
getInspectPorts(extensionHostKind: ExtensionHostKind, tryEnableInspector: boolean): Promise<number[]>;
getInspectPorts(extensionHostKind: ExtensionHostKind, tryEnableInspector: boolean): Promise<{ port: number; host: string }[]>;

/**
* Stops the extension hosts.
Expand Down Expand Up @@ -585,7 +585,7 @@ export class NullExtensionService implements IExtensionService {
getExtension() { return Promise.resolve(undefined); }
readExtensionPointContributions<T>(_extPoint: IExtensionPoint<T>): Promise<ExtensionPointContribution<T>[]> { return Promise.resolve(Object.create(null)); }
getExtensionsStatus(): { [id: string]: IExtensionsStatus } { return Object.create(null); }
getInspectPorts(_extensionHostKind: ExtensionHostKind, _tryEnableInspector: boolean): Promise<number[]> { return Promise.resolve([]); }
getInspectPorts(_extensionHostKind: ExtensionHostKind, _tryEnableInspector: boolean): Promise<{ port: number; host: string }[]> { return Promise.resolve([]); }
stopExtensionHosts(): any { }
async startExtensionHosts(): Promise<void> { }
async setRemoteEnvironment(_env: { [key: string]: string | null }): Promise<void> { }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,12 +137,9 @@ export class LazyCreateExtensionHostManager extends Disposable implements IExten
}
return true;
}
public async getInspectPort(tryEnableInspector: boolean): Promise<number> {
public async getInspectPort(tryEnableInspector: boolean): Promise<{ port: number; host: string } | undefined> {
await this._startCalled.wait();
if (this._actual) {
return this._actual.getInspectPort(tryEnableInspector);
}
return 0;
return this._actual?.getInspectPort(tryEnableInspector);
}
public async resolveAuthority(remoteAuthority: string, resolveAttempt: number): Promise<IResolveAuthorityResult> {
await this._startCalled.wait();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ export class RemoteExtensionHost extends Disposable implements IExtensionHost {
};
}

getInspectPort(): number | undefined {
getInspectPort(): undefined {
return undefined;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { createSingleCallFunction } from 'vs/base/common/functional';
export class ExtensionHostProfiler {

constructor(
private readonly _host: string,
private readonly _port: number,
@IExtensionService private readonly _extensionService: IExtensionService,
@IV8InspectProfilingService private readonly _profilingService: IV8InspectProfilingService,
Expand All @@ -22,7 +23,7 @@ export class ExtensionHostProfiler {

public async start(): Promise<ProfileSession> {

const id = await this._profilingService.startProfiling({ port: this._port });
const id = await this._profilingService.startProfiling({ host: this._host, port: this._port });

return {
stop: createSingleCallFunction(async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ export class NativeLocalProcessExtensionHost implements IExtensionHost {
private _terminating: boolean;

// Resources, in order they get acquired/created when .start() is called:
private _inspectPort: number | null;
private _inspectListener: { port: number; host: string } | null;
private _extensionHostProcess: ExtensionHostProcess | null;
private _messageProtocol: Promise<IMessagePassingProtocol> | null;

Expand Down Expand Up @@ -141,7 +141,7 @@ export class NativeLocalProcessExtensionHost implements IExtensionHost {

this._terminating = false;

this._inspectPort = null;
this._inspectListener = null;
this._extensionHostProcess = null;
this._messageProtocol = null;

Expand Down Expand Up @@ -221,10 +221,11 @@ export class NativeLocalProcessExtensionHost implements IExtensionHost {
silent: true
};

const inspectHost = '127.0.0.1';
if (portNumber !== 0) {
opts.execArgv = [
'--nolazy',
(this._isExtensionDevDebugBrk ? '--inspect-brk=' : '--inspect=') + portNumber
(this._isExtensionDevDebugBrk ? '--inspect-brk=' : '--inspect=') + `${inspectHost}:${portNumber}`
];
} else {
opts.execArgv = ['--inspect-port=0'];
Expand Down Expand Up @@ -259,13 +260,14 @@ export class NativeLocalProcessExtensionHost implements IExtensionHost {

// Print out extension host output
this._toDispose.add(onDebouncedOutput(output => {
const inspectorUrlMatch = output.data && output.data.match(/ws:\/\/([^\s]+:(\d+)\/[^\s]+)/);
const inspectorUrlMatch = output.data && output.data.match(/ws:\/\/([^\s]+):(\d+)\/[^\s]+/);
if (inspectorUrlMatch) {
const [, host, port] = inspectorUrlMatch;
if (!this._environmentService.isBuilt && !this._isExtensionDevTestFromCli) {
console.log(`%c[Extension Host] %cdebugger inspector at devtools:https://devtools/bundled/inspector.html?experiments=true&v8only=true&ws=${inspectorUrlMatch[1]}`, 'color: blue', 'color:');
}
if (!this._inspectPort) {
this._inspectPort = Number(inspectorUrlMatch[2]);
if (!this._inspectListener) {
this._inspectListener = { host, port: Number(port) };
this._onDidSetInspectPort.fire();
}
} else {
Expand All @@ -283,10 +285,10 @@ export class NativeLocalProcessExtensionHost implements IExtensionHost {

// Notify debugger that we are ready to attach to the process if we run a development extension
if (portNumber) {
if (this._isExtensionDevHost && portNumber && this._isExtensionDevDebug && this._environmentService.debugExtensionHost.debugId) {
if (this._isExtensionDevHost && this._isExtensionDevDebug && this._environmentService.debugExtensionHost.debugId) {
this._extensionHostDebugService.attachSession(this._environmentService.debugExtensionHost.debugId, portNumber);
}
this._inspectPort = portNumber;
this._inspectListener = { port: portNumber, host: inspectHost };
this._onDidSetInspectPort.fire();
}

Expand Down Expand Up @@ -555,7 +557,7 @@ export class NativeLocalProcessExtensionHost implements IExtensionHost {
}

public async enableInspectPort(): Promise<boolean> {
if (typeof this._inspectPort === 'number') {
if (!!this._inspectListener) {
return true;
}

Expand All @@ -569,11 +571,11 @@ export class NativeLocalProcessExtensionHost implements IExtensionHost {
}

await Promise.race([Event.toPromise(this._onDidSetInspectPort.event), timeout(1000)]);
return typeof this._inspectPort === 'number';
return !!this._inspectListener;
}

public getInspectPort(): number | undefined {
return this._inspectPort ?? undefined;
public getInspectPort(): { port: number; host: string } | undefined {
return this._inspectListener ?? undefined;
}

private _onWillShutdown(event: WillShutdownEvent): void {
Expand Down
18 changes: 9 additions & 9 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2614,10 +2614,10 @@ chownr@^2.0.0:
resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece"
integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==

chrome-remote-interface@0.28.2:
version "0.28.2"
resolved "https://registry.yarnpkg.com/chrome-remote-interface/-/chrome-remote-interface-0.28.2.tgz#6be3554d2c227ff07eb74baa7e5d4911da12a5a6"
integrity sha512-F7mjof7rWvRNsJqhVXuiFU/HWySCxTA9tzpLxUJxVfdLkljwFJ1aMp08AnwXRmmP7r12/doTDOMwaNhFCJsacw==
chrome-remote-interface@^0.33.0:
version "0.33.0"
resolved "https://registry.yarnpkg.com/chrome-remote-interface/-/chrome-remote-interface-0.33.0.tgz#9140b5612ee5cdc39212cd0296d3b61ea881c47a"
integrity sha512-tv/SgeBfShXk43fwFpQ9wnS7mOCPzETnzDXTNxCb6TqKOiOeIfbrJz+2NAp8GmzwizpKa058wnU1Te7apONaYg==
dependencies:
commander "2.11.x"
ws "^7.2.0"
Expand Down Expand Up @@ -9768,12 +9768,12 @@ v8-compile-cache-lib@^3.0.1:
resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf"
integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==

v8-inspect-profiler@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/v8-inspect-profiler/-/v8-inspect-profiler-0.1.0.tgz#0d3f80e2dc878f737c31ae7ff4c033425a33a724"
integrity sha512-K7RyY4p59+rIPvgcTN/Oo7VU9cJ68LOl+dz8RCh/M4VwbZ9yS3Ci+qajbMDojW207anNn7CehkLvqpSIrNT9oA==
v8-inspect-profiler@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/v8-inspect-profiler/-/v8-inspect-profiler-0.1.1.tgz#52fd9f1234dca2f650063c6cd39bdaef47b49396"
integrity sha512-GB3X9w7w+y9v4gq85olmf/bM3F2hj2DjjwvVpDXIziW5JBy8cDcIQ/K7m8xJVDWiFemxRX2Dxoo1k6JDvLMTig==
dependencies:
chrome-remote-interface "0.28.2"
chrome-remote-interface "^0.33.0"

v8-to-istanbul@^9.0.0:
version "9.2.0"
Expand Down

0 comments on commit 7a523c2

Please sign in to comment.