提交 46d1ac2b 编写于 作者: A Alex Dima

Add "Measure Extension Host Latency" action

上级 e44801f2
......@@ -739,6 +739,10 @@ export interface ExtHostExtensionServiceShape {
$resolveAuthority(remoteAuthority: string): Promise<ResolvedAuthority>;
$startExtensionHost(enabledExtensionIds: ExtensionIdentifier[]): Promise<void>;
$activateByEvent(activationEvent: string): Promise<void>;
$test_latency(n: number): Promise<number>;
$test_up(b: Buffer): Promise<number>;
$test_down(size: number): Promise<Buffer>;
}
export interface FileSystemEvents {
......
......@@ -646,6 +646,20 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
.then(_ => this._activateByEvent(activationEvent, false))
);
}
public async $test_latency(n: number): Promise<number> {
return n;
}
public async $test_up(b: Buffer): Promise<number> {
return b.length;
}
public async $test_down(size: number): Promise<Buffer> {
let b = Buffer.alloc(size, Math.random() % 256);
return b;
}
}
function loadCommonJSModule<T>(logService: ILogService, modulePath: string, activationTimesBuilder: ExtensionActivationTimesBuilder): Promise<T> {
......
......@@ -19,6 +19,14 @@ import { ProxyIdentifier } from 'vs/workbench/services/extensions/node/proxyIden
import { IRPCProtocolLogger, RPCProtocol, RequestInitiator, ResponsiveState } from 'vs/workbench/services/extensions/node/rpcProtocol';
import { ResolvedAuthority } from 'vs/platform/remote/common/remoteAuthorityResolver';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import * as nls from 'vs/nls';
import { Action } from 'vs/base/common/actions';
import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
import { Registry } from 'vs/platform/registry/common/platform';
import { Extensions as ActionExtensions, IWorkbenchActionRegistry } from 'vs/workbench/common/actions';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IUntitledResourceInput } from 'vs/workbench/common/editor';
import { StopWatch } from 'vs/base/common/stopwatch';
// Enable to see detailed message communication between window and extension host
const LOG_EXTENSION_HOST_COMMUNICATION = false;
......@@ -71,6 +79,9 @@ export class ExtensionHostProcessManager extends Disposable {
);
this._extensionHostProcessProxy.then(() => {
initialActivationEvents.forEach((activationEvent) => this.activateByEvent(activationEvent));
this._register(registerLatencyTestProvider({
measure: () => this.measure()
}));
});
}
......@@ -94,6 +105,57 @@ export class ExtensionHostProcessManager extends Disposable {
super.dispose();
}
private async measure(): Promise<ExtHostLatencyResult> {
const latency = await this._measureLatency();
const down = await this._measureDown();
const up = await this._measureUp();
return {
remoteAuthority: this._remoteAuthority,
latency,
down,
up
};
}
private async _measureLatency(): Promise<number> {
const COUNT = 10;
const { value: proxy } = await this._extensionHostProcessProxy;
let sum = 0;
for (let i = 0; i < COUNT; i++) {
const sw = StopWatch.create(true);
await proxy.$test_latency(i);
sw.stop();
sum += sw.elapsed();
}
return (sum / COUNT);
}
private static _convert(byteCount: number, elapsedMillis: number): number {
return (byteCount * 1000 * 8) / elapsedMillis;
}
private async _measureUp(): Promise<number> {
const SIZE = 10 * 1024 * 1024; // 10MB
const { value: proxy } = await this._extensionHostProcessProxy;
let b = Buffer.alloc(SIZE, Math.random() % 256);
const sw = StopWatch.create(true);
await proxy.$test_up(b);
sw.stop();
return ExtensionHostProcessManager._convert(SIZE, sw.elapsed());
}
private async _measureDown(): Promise<number> {
const SIZE = 10 * 1024 * 1024; // 10MB
const { value: proxy } = await this._extensionHostProcessProxy;
const sw = StopWatch.create(true);
await proxy.$test_down(SIZE);
sw.stop();
return ExtensionHostProcessManager._convert(SIZE, sw.elapsed());
}
public canProfileExtensionHost(): boolean {
return this._extensionHostProcessWorker && Boolean(this._extensionHostProcessWorker.getInspectPort());
}
......@@ -238,3 +300,68 @@ class RPCLogger implements IRPCProtocolLogger {
this._log('Win \u2192 Ext', this._totalOutgoing, msgLength, req, initiator, str, data);
}
}
interface ExtHostLatencyResult {
remoteAuthority: string;
up: number;
down: number;
latency: number;
}
interface ExtHostLatencyProvider {
measure(): Promise<ExtHostLatencyResult>;
}
let providers: ExtHostLatencyProvider[] = [];
function registerLatencyTestProvider(provider: ExtHostLatencyProvider): IDisposable {
providers.push(provider);
return {
dispose: () => {
for (let i = 0; i < providers.length; i++) {
if (providers[i] === provider) {
providers.splice(i, 1);
return;
}
}
}
};
}
function getLatencyTestProviders(): ExtHostLatencyProvider[] {
return providers.slice(0);
}
export class MeasureExtHostLatencyAction extends Action {
public static readonly ID = 'editor.action.measureExtHostLatency';
public static readonly LABEL = nls.localize('measureExtHostLatency', "Developer: Measure Extension Host Latency");
constructor(
id: string,
label: string,
@IEditorService private readonly _editorService: IEditorService
) {
super(id, label);
}
public async run(): Promise<any> {
const measurements = await Promise.all(getLatencyTestProviders().map(provider => provider.measure()));
this._editorService.openEditor({ contents: measurements.map(MeasureExtHostLatencyAction._print).join('\n\n'), options: { pinned: true } } as IUntitledResourceInput);
}
private static _print(m: ExtHostLatencyResult): string {
return `${m.remoteAuthority ? `Authority: ${m.remoteAuthority}\n` : ``}Roundtrip latency: ${m.latency.toFixed(3)}ms\nUp: ${MeasureExtHostLatencyAction._printSpeed(m.up)}\nDown: ${MeasureExtHostLatencyAction._printSpeed(m.down)}\n`;
}
private static _printSpeed(n: number): string {
if (n <= 1024) {
return `${n} bps`;
}
if (n < 1024 * 1024) {
return `${(n / 1024).toFixed(1)} kbps`;
}
return `${(n / 1024 / 1024).toFixed(1)} Mbps`;
}
}
const registry = Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions);
registry.registerWorkbenchAction(new SyncActionDescriptor(MeasureExtHostLatencyAction, MeasureExtHostLatencyAction.ID, MeasureExtHostLatencyAction.LABEL), 'Developer: Measure Extension Host Latency');
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册