diff --git a/src/vs/workbench/api/browser/mainThreadTerminalService.ts b/src/vs/workbench/api/browser/mainThreadTerminalService.ts index 831ed07a77e..85cdee88e32 100644 --- a/src/vs/workbench/api/browser/mainThreadTerminalService.ts +++ b/src/vs/workbench/api/browser/mainThreadTerminalService.ts @@ -8,6 +8,7 @@ import { ITerminalService, ITerminalInstance, IShellLaunchConfig, ITerminalProce import { ExtHostContext, ExtHostTerminalServiceShape, MainThreadTerminalServiceShape, MainContext, IExtHostContext, ShellLaunchConfigDto } from 'vs/workbench/api/common/extHost.protocol'; import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers'; import { UriComponents, URI } from 'vs/base/common/uri'; +import { StopWatch } from 'vs/base/common/stopwatch'; @extHostNamedCustomer(MainContext.MainThreadTerminalService) export class MainThreadTerminalService implements MainThreadTerminalServiceShape { @@ -227,6 +228,7 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape request.proxy.onShutdown(immediate => this._proxy.$acceptProcessShutdown(request.proxy.terminalId, immediate)); request.proxy.onRequestCwd(() => this._proxy.$acceptProcessRequestCwd(request.proxy.terminalId)); request.proxy.onRequestInitialCwd(() => this._proxy.$acceptProcessRequestInitialCwd(request.proxy.terminalId)); + request.proxy.onRequestLatency(() => this._onRequestLatency(request.proxy.terminalId)); } public $sendProcessTitle(terminalId: number, title: string): void { @@ -253,4 +255,16 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape public $sendProcessCwd(terminalId: number, cwd: string): void { this._terminalProcesses[terminalId].emitCwd(cwd); } + + private async _onRequestLatency(terminalId: number): Promise { + const COUNT = 2; + let sum = 0; + for (let i = 0; i < COUNT; i++) { + const sw = StopWatch.create(true); + await this._proxy.$acceptProcessRequestLatency(terminalId); + sw.stop(); + sum += sw.elapsed(); + } + this._terminalProcesses[terminalId].emitLatency(sum / COUNT); + } } diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 050c2665b02..e28790f4c98 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -1041,6 +1041,7 @@ export interface ExtHostTerminalServiceShape { $acceptProcessShutdown(id: number, immediate: boolean): void; $acceptProcessRequestInitialCwd(id: number): void; $acceptProcessRequestCwd(id: number): void; + $acceptProcessRequestLatency(id: number): number; } export interface ExtHostSCMShape { diff --git a/src/vs/workbench/api/node/extHostTerminalService.ts b/src/vs/workbench/api/node/extHostTerminalService.ts index c9705e60f82..b5a3737c6b6 100644 --- a/src/vs/workbench/api/node/extHostTerminalService.ts +++ b/src/vs/workbench/api/node/extHostTerminalService.ts @@ -529,6 +529,10 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape { this._terminalProcesses[id].getCwd().then(cwd => this._proxy.$sendProcessCwd(id, cwd)); } + public $acceptProcessRequestLatency(id: number): number { + return id; + } + private _onProcessExit(id: number, exitCode: number): void { // Remove listeners this._terminalProcesses[id].dispose(); diff --git a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts index a721e961983..23061548e78 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts @@ -27,6 +27,11 @@ import { IRemoteEnvironmentService } from 'vs/workbench/services/remote/common/r /** The amount of time to consider terminal errors to be related to the launch */ const LAUNCHING_DURATION = 500; +/** + * The minimum amount of time between latency requests. + */ +const LATENCY_MEASURING_INTERVAL = 1000; + /** * Holds all state related to the creation and management of terminal processes. * @@ -46,6 +51,9 @@ export class TerminalProcessManager implements ITerminalProcessManager { private _process: ITerminalChildProcess | null = null; private _preLaunchInputQueue: string[] = []; private _disposables: IDisposable[] = []; + private _latency: number = -1; + private _latencyRequest: Promise; + private _latencyLastMeasured: number = 0; private readonly _onProcessReady = new Emitter(); public get onProcessReady(): Event { return this._onProcessReady.event; } @@ -77,6 +85,7 @@ export class TerminalProcessManager implements ITerminalProcessManager { c(undefined); }); }); + this.ptyProcessReady.then(async () => await this.getLatency()); } public dispose(immediate: boolean = false): void { @@ -240,6 +249,18 @@ export class TerminalProcessManager implements ITerminalProcessManager { return this._process.getCwd(); } + public async getLatency(): Promise { + if (!this._process) { + return Promise.resolve(0); + } + if (this._latencyLastMeasured === 0 || this._latencyLastMeasured + LATENCY_MEASURING_INTERVAL < Date.now()) { + this._latencyRequest = this._process.getLatency(); + this._latency = await this._latencyRequest; + this._latencyLastMeasured = Date.now(); + } + return Promise.resolve(this._latency); + } + private _onExit(exitCode: number): void { this._process = null; diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index c66e1da4003..1c6188e757d 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -654,6 +654,7 @@ export interface ITerminalProcessManager extends IDisposable { getInitialCwd(): Promise; getCwd(): Promise; + getLatency(): Promise; } export const enum ProcessState { @@ -685,12 +686,14 @@ export interface ITerminalProcessExtHostProxy extends IDisposable { emitExit(exitCode: number): void; emitInitialCwd(initialCwd: string): void; emitCwd(cwd: string): void; + emitLatency(latency: number): void; onInput: Event; onResize: Event<{ cols: number, rows: number }>; onShutdown: Event; onRequestInitialCwd: Event; onRequestCwd: Event; + onRequestLatency: Event; } export interface ITerminalProcessExtHostRequest { @@ -733,4 +736,5 @@ export interface ITerminalChildProcess { getInitialCwd(): Promise; getCwd(): Promise; + getLatency(): Promise; } \ No newline at end of file diff --git a/src/vs/workbench/contrib/terminal/common/terminalProcessExtHostProxy.ts b/src/vs/workbench/contrib/terminal/common/terminalProcessExtHostProxy.ts index 84131aa9edd..ed89adc9c7d 100644 --- a/src/vs/workbench/contrib/terminal/common/terminalProcessExtHostProxy.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalProcessExtHostProxy.ts @@ -31,9 +31,12 @@ export class TerminalProcessExtHostProxy implements ITerminalChildProcess, ITerm public get onRequestInitialCwd(): Event { return this._onRequestInitialCwd.event; } private readonly _onRequestCwd = new Emitter(); public get onRequestCwd(): Event { return this._onRequestCwd.event; } + private readonly _onRequestLatency = new Emitter(); + public get onRequestLatency(): Event { return this._onRequestLatency.event; } private _pendingInitialCwdRequests: ((value?: string | Thenable) => void)[] = []; private _pendingCwdRequests: ((value?: string | Thenable) => void)[] = []; + private _pendingLatencyRequests: ((value?: number | Thenable) => void)[] = []; constructor( public terminalId: number, @@ -86,6 +89,12 @@ export class TerminalProcessExtHostProxy implements ITerminalChildProcess, ITerm } } + public emitLatency(latency: number): void { + while (this._pendingLatencyRequests.length > 0) { + this._pendingLatencyRequests.pop()!(latency); + } + } + public shutdown(immediate: boolean): void { this._onShutdown.fire(immediate); } @@ -111,4 +120,11 @@ export class TerminalProcessExtHostProxy implements ITerminalChildProcess, ITerm this._pendingCwdRequests.push(resolve); }); } + + public getLatency(): Promise { + return new Promise(resolve => { + this._onRequestLatency.fire(); + this._pendingLatencyRequests.push(resolve); + }); + } } \ No newline at end of file diff --git a/src/vs/workbench/contrib/terminal/node/terminalProcess.ts b/src/vs/workbench/contrib/terminal/node/terminalProcess.ts index 3d40e7ed804..16488ef5287 100644 --- a/src/vs/workbench/contrib/terminal/node/terminalProcess.ts +++ b/src/vs/workbench/contrib/terminal/node/terminalProcess.ts @@ -213,4 +213,8 @@ export class TerminalProcess implements ITerminalChildProcess, IDisposable { resolve(this._initialCwd); }); } + + public getLatency(): Promise { + return Promise.resolve(0); + } }