Skip to content

Commit f2f7a8e

Browse files
authored
Merge pull request microsoft#185668 from microsoft/tyriar/measure
Measure and report basic terminal performance marks
2 parents 7288d30 + 93f78ed commit f2f7a8e

File tree

3 files changed

+43
-8
lines changed

3 files changed

+43
-8
lines changed

src/vs/workbench/contrib/performance/browser/perfviewEditor.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { ByteSize, IFileService } from 'vs/platform/files/common/files';
2525
import { ILabelService } from 'vs/platform/label/common/label';
2626
import { isWeb } from 'vs/base/common/platform';
2727
import { IFilesConfigurationService } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService';
28+
import { ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal';
2829

2930
export class PerfviewContrib {
3031

@@ -87,7 +88,8 @@ class PerfModelContentProvider implements ITextModelContentProvider {
8788
@ILifecycleService private readonly _lifecycleService: ILifecycleService,
8889
@ITimerService private readonly _timerService: ITimerService,
8990
@IExtensionService private readonly _extensionService: IExtensionService,
90-
@IProductService private readonly _productService: IProductService
91+
@IProductService private readonly _productService: IProductService,
92+
@ITerminalService private readonly _terminalService: ITerminalService
9193
) { }
9294

9395
provideTextContent(resource: URI): Promise<ITextModel> {
@@ -113,7 +115,8 @@ class PerfModelContentProvider implements ITextModelContentProvider {
113115
Promise.all([
114116
this._timerService.whenReady(),
115117
this._lifecycleService.when(LifecyclePhase.Eventually),
116-
this._extensionService.whenInstalledExtensionsRegistered()
118+
this._extensionService.whenInstalledExtensionsRegistered(),
119+
this._terminalService.whenConnected
117120
]).then(() => {
118121
if (this._model && !this._model.isDisposed()) {
119122

src/vs/workbench/contrib/terminal/browser/terminal.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ export interface ITerminalService extends ITerminalInstanceHost {
157157
configHelper: ITerminalConfigHelper;
158158
isProcessSupportRegistered: boolean;
159159
readonly connectionState: TerminalConnectionState;
160+
readonly whenConnected: Promise<void>;
160161
readonly defaultLocation: TerminalLocation;
161162

162163
onDidChangeActiveGroup: Event<ITerminalGroup | undefined>;

src/vs/workbench/contrib/terminal/browser/terminalService.ts

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import * as dom from 'vs/base/browser/dom';
7-
import { timeout } from 'vs/base/common/async';
7+
import { DeferredPromise, timeout } from 'vs/base/common/async';
88
import { debounce } from 'vs/base/common/decorators';
99
import { Emitter, Event } from 'vs/base/common/event';
1010
import { dispose, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
@@ -51,6 +51,7 @@ import { XtermTerminal } from 'vs/workbench/contrib/terminal/browser/xterm/xterm
5151
import { TerminalInstance } from 'vs/workbench/contrib/terminal/browser/terminalInstance';
5252
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
5353
import { TerminalCapabilityStore } from 'vs/platform/terminal/common/capabilities/terminalCapabilityStore';
54+
import { ITimerService } from 'vs/workbench/services/timer/browser/timerService';
5455

5556
export class TerminalService implements ITerminalService {
5657
declare _serviceBrand: undefined;
@@ -70,15 +71,19 @@ export class TerminalService implements ITerminalService {
7071
private _terminalHasBeenCreated: IContextKey<boolean>;
7172
private _terminalCountContextKey: IContextKey<number>;
7273
private _configHelper: TerminalConfigHelper;
73-
private _connectionState: TerminalConnectionState = TerminalConnectionState.Connecting;
7474
private _nativeDelegate?: ITerminalServiceNativeDelegate;
7575
private _shutdownWindowCount?: number;
7676

7777
private _editable: { instance: ITerminalInstance; data: IEditableData } | undefined;
7878

7979
get isProcessSupportRegistered(): boolean { return !!this._processSupportContextKey.get(); }
80+
81+
private _connectionState: TerminalConnectionState = TerminalConnectionState.Connecting;
8082
get connectionState(): TerminalConnectionState { return this._connectionState; }
8183

84+
private readonly _whenConnected = new DeferredPromise<void>();
85+
get whenConnected(): Promise<void> { return this._whenConnected.p; }
86+
8287
get configHelper(): ITerminalConfigHelper { return this._configHelper; }
8388
get instances(): ITerminalInstance[] {
8489
return this._terminalGroupService.instances.concat(this._terminalEditorService.instances);
@@ -170,7 +175,8 @@ export class TerminalService implements ITerminalService {
170175
@INotificationService private readonly _notificationService: INotificationService,
171176
@IWorkspaceContextService private readonly _workspaceContextService: IWorkspaceContextService,
172177
@ICommandService private readonly _commandService: ICommandService,
173-
@IKeybindingService private readonly _keybindingService: IKeybindingService
178+
@IKeybindingService private readonly _keybindingService: IKeybindingService,
179+
@ITimerService private readonly _timerService: ITimerService
174180
) {
175181
this._configHelper = this._instantiationService.createInstance(TerminalConfigHelper);
176182
// the below avoids having to poll routinely.
@@ -259,8 +265,15 @@ export class TerminalService implements ITerminalService {
259265
return undefined;
260266
}
261267

268+
private readonly _perfMarks: PerformanceMark[] = [];
269+
private _mark(name: string) {
270+
this._perfMarks.push(new PerformanceMark(name));
271+
}
272+
262273
async initializePrimaryBackend() {
274+
this._mark('code/terminal/willGetTerminalBackend');
263275
this._primaryBackend = await this._terminalInstanceService.getBackend(this._environmentService.remoteAuthority);
276+
this._mark('code/terminal/didGetTerminalBackend');
264277
const enableTerminalReconnection = this.configHelper.config.enablePersistentSessions;
265278

266279
// Connect to the extension host if it's there, set the connection state to connected when
@@ -269,13 +282,21 @@ export class TerminalService implements ITerminalService {
269282

270283
const isPersistentRemote = !!this._environmentService.remoteAuthority && enableTerminalReconnection;
271284

285+
this._mark('code/terminal/willReconnect');
286+
let reconnectedPromise: Promise<any>;
272287
if (isPersistentRemote) {
273-
this._reconnectToRemoteTerminals().then(() => this._setConnected());
288+
reconnectedPromise = this._reconnectToRemoteTerminals();
274289
} else if (enableTerminalReconnection) {
275-
this._reconnectToLocalTerminals().then(() => this._setConnected());
290+
reconnectedPromise = this._reconnectToLocalTerminals();
276291
} else {
277-
Promise.resolve().then(() => this._setConnected());
292+
reconnectedPromise = Promise.resolve();
278293
}
294+
reconnectedPromise.then(() => {
295+
this._setConnected();
296+
this._mark('code/terminal/didReconnect');
297+
this._timerService.setPerformanceMarks('terminal', this._perfMarks);
298+
this._whenConnected.complete();
299+
});
279300

280301
this._primaryBackend?.onDidRequestDetach(async (e) => {
281302
const instanceToDetach = this.getInstanceFromResource(getTerminalUri(e.workspaceId, e.instanceId));
@@ -404,9 +425,13 @@ export class TerminalService implements ITerminalService {
404425
if (!backend) {
405426
return;
406427
}
428+
this._mark('code/terminal/willGetTerminalLayoutInfo');
407429
const layoutInfo = await backend.getTerminalLayoutInfo();
430+
this._mark('code/terminal/didGetTerminalLayoutInfo');
408431
backend.reduceConnectionGraceTime();
432+
this._mark('code/terminal/willRecreateTerminalGroups');
409433
await this._recreateTerminalGroups(layoutInfo);
434+
this._mark('code/terminal/didRecreateTerminalGroups');
410435
// now that terminals have been restored,
411436
// attach listeners to update remote when terminals are changed
412437
this._attachProcessLayoutListeners();
@@ -417,9 +442,13 @@ export class TerminalService implements ITerminalService {
417442
if (!localBackend) {
418443
return;
419444
}
445+
this._mark('code/terminal/willGetTerminalLayoutInfo');
420446
const layoutInfo = await localBackend.getTerminalLayoutInfo();
447+
this._mark('code/terminal/didGetTerminalLayoutInfo');
421448
if (layoutInfo && layoutInfo.tabs.length > 0) {
449+
this._mark('code/terminal/willRecreateTerminalGroups');
422450
await this._recreateTerminalGroups(layoutInfo);
451+
this._mark('code/terminal/didRecreateTerminalGroups');
423452
}
424453
// now that terminals have been restored,
425454
// attach listeners to update local state when terminals are changed
@@ -437,6 +466,7 @@ export class TerminalService implements ITerminalService {
437466
let terminalInstance: ITerminalInstance | undefined;
438467
let group: ITerminalGroup | undefined;
439468
for (const terminalLayout of terminalLayouts) {
469+
this._mark(`code/terminal/willRecreateTerminal/${terminalLayout.terminal?.id}`);
440470
if (this._lifecycleService.startupKind !== StartupKind.ReloadedWindow && terminalLayout.terminal?.type === 'Task') {
441471
continue;
442472
}
@@ -457,6 +487,7 @@ export class TerminalService implements ITerminalService {
457487
location: { parentTerminal: terminalInstance }
458488
});
459489
}
490+
this._mark(`code/terminal/didRecreateTerminal/${terminalLayout.terminal?.id}`);
460491
}
461492
const activeInstance = this.instances.find(t => {
462493
return t.shellLaunchConfig.attachPersistentProcess?.id === groupLayout.activePersistentProcessId;

0 commit comments

Comments
 (0)