4
4
*--------------------------------------------------------------------------------------------*/
5
5
6
6
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' ;
8
8
import { debounce } from 'vs/base/common/decorators' ;
9
9
import { Emitter , Event } from 'vs/base/common/event' ;
10
10
import { dispose , IDisposable , toDisposable } from 'vs/base/common/lifecycle' ;
@@ -51,6 +51,7 @@ import { XtermTerminal } from 'vs/workbench/contrib/terminal/browser/xterm/xterm
51
51
import { TerminalInstance } from 'vs/workbench/contrib/terminal/browser/terminalInstance' ;
52
52
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding' ;
53
53
import { TerminalCapabilityStore } from 'vs/platform/terminal/common/capabilities/terminalCapabilityStore' ;
54
+ import { ITimerService } from 'vs/workbench/services/timer/browser/timerService' ;
54
55
55
56
export class TerminalService implements ITerminalService {
56
57
declare _serviceBrand : undefined ;
@@ -70,15 +71,19 @@ export class TerminalService implements ITerminalService {
70
71
private _terminalHasBeenCreated : IContextKey < boolean > ;
71
72
private _terminalCountContextKey : IContextKey < number > ;
72
73
private _configHelper : TerminalConfigHelper ;
73
- private _connectionState : TerminalConnectionState = TerminalConnectionState . Connecting ;
74
74
private _nativeDelegate ?: ITerminalServiceNativeDelegate ;
75
75
private _shutdownWindowCount ?: number ;
76
76
77
77
private _editable : { instance : ITerminalInstance ; data : IEditableData } | undefined ;
78
78
79
79
get isProcessSupportRegistered ( ) : boolean { return ! ! this . _processSupportContextKey . get ( ) ; }
80
+
81
+ private _connectionState : TerminalConnectionState = TerminalConnectionState . Connecting ;
80
82
get connectionState ( ) : TerminalConnectionState { return this . _connectionState ; }
81
83
84
+ private readonly _whenConnected = new DeferredPromise < void > ( ) ;
85
+ get whenConnected ( ) : Promise < void > { return this . _whenConnected . p ; }
86
+
82
87
get configHelper ( ) : ITerminalConfigHelper { return this . _configHelper ; }
83
88
get instances ( ) : ITerminalInstance [ ] {
84
89
return this . _terminalGroupService . instances . concat ( this . _terminalEditorService . instances ) ;
@@ -170,7 +175,8 @@ export class TerminalService implements ITerminalService {
170
175
@INotificationService private readonly _notificationService : INotificationService ,
171
176
@IWorkspaceContextService private readonly _workspaceContextService : IWorkspaceContextService ,
172
177
@ICommandService private readonly _commandService : ICommandService ,
173
- @IKeybindingService private readonly _keybindingService : IKeybindingService
178
+ @IKeybindingService private readonly _keybindingService : IKeybindingService ,
179
+ @ITimerService private readonly _timerService : ITimerService
174
180
) {
175
181
this . _configHelper = this . _instantiationService . createInstance ( TerminalConfigHelper ) ;
176
182
// the below avoids having to poll routinely.
@@ -259,8 +265,15 @@ export class TerminalService implements ITerminalService {
259
265
return undefined ;
260
266
}
261
267
268
+ private readonly _perfMarks : PerformanceMark [ ] = [ ] ;
269
+ private _mark ( name : string ) {
270
+ this . _perfMarks . push ( new PerformanceMark ( name ) ) ;
271
+ }
272
+
262
273
async initializePrimaryBackend ( ) {
274
+ this . _mark ( 'code/terminal/willGetTerminalBackend' ) ;
263
275
this . _primaryBackend = await this . _terminalInstanceService . getBackend ( this . _environmentService . remoteAuthority ) ;
276
+ this . _mark ( 'code/terminal/didGetTerminalBackend' ) ;
264
277
const enableTerminalReconnection = this . configHelper . config . enablePersistentSessions ;
265
278
266
279
// 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 {
269
282
270
283
const isPersistentRemote = ! ! this . _environmentService . remoteAuthority && enableTerminalReconnection ;
271
284
285
+ this . _mark ( 'code/terminal/willReconnect' ) ;
286
+ let reconnectedPromise : Promise < any > ;
272
287
if ( isPersistentRemote ) {
273
- this . _reconnectToRemoteTerminals ( ) . then ( ( ) => this . _setConnected ( ) ) ;
288
+ reconnectedPromise = this . _reconnectToRemoteTerminals ( ) ;
274
289
} else if ( enableTerminalReconnection ) {
275
- this . _reconnectToLocalTerminals ( ) . then ( ( ) => this . _setConnected ( ) ) ;
290
+ reconnectedPromise = this . _reconnectToLocalTerminals ( ) ;
276
291
} else {
277
- Promise . resolve ( ) . then ( ( ) => this . _setConnected ( ) ) ;
292
+ reconnectedPromise = Promise . resolve ( ) ;
278
293
}
294
+ reconnectedPromise . then ( ( ) => {
295
+ this . _setConnected ( ) ;
296
+ this . _mark ( 'code/terminal/didReconnect' ) ;
297
+ this . _timerService . setPerformanceMarks ( 'terminal' , this . _perfMarks ) ;
298
+ this . _whenConnected . complete ( ) ;
299
+ } ) ;
279
300
280
301
this . _primaryBackend ?. onDidRequestDetach ( async ( e ) => {
281
302
const instanceToDetach = this . getInstanceFromResource ( getTerminalUri ( e . workspaceId , e . instanceId ) ) ;
@@ -404,9 +425,13 @@ export class TerminalService implements ITerminalService {
404
425
if ( ! backend ) {
405
426
return ;
406
427
}
428
+ this . _mark ( 'code/terminal/willGetTerminalLayoutInfo' ) ;
407
429
const layoutInfo = await backend . getTerminalLayoutInfo ( ) ;
430
+ this . _mark ( 'code/terminal/didGetTerminalLayoutInfo' ) ;
408
431
backend . reduceConnectionGraceTime ( ) ;
432
+ this . _mark ( 'code/terminal/willRecreateTerminalGroups' ) ;
409
433
await this . _recreateTerminalGroups ( layoutInfo ) ;
434
+ this . _mark ( 'code/terminal/didRecreateTerminalGroups' ) ;
410
435
// now that terminals have been restored,
411
436
// attach listeners to update remote when terminals are changed
412
437
this . _attachProcessLayoutListeners ( ) ;
@@ -417,9 +442,13 @@ export class TerminalService implements ITerminalService {
417
442
if ( ! localBackend ) {
418
443
return ;
419
444
}
445
+ this . _mark ( 'code/terminal/willGetTerminalLayoutInfo' ) ;
420
446
const layoutInfo = await localBackend . getTerminalLayoutInfo ( ) ;
447
+ this . _mark ( 'code/terminal/didGetTerminalLayoutInfo' ) ;
421
448
if ( layoutInfo && layoutInfo . tabs . length > 0 ) {
449
+ this . _mark ( 'code/terminal/willRecreateTerminalGroups' ) ;
422
450
await this . _recreateTerminalGroups ( layoutInfo ) ;
451
+ this . _mark ( 'code/terminal/didRecreateTerminalGroups' ) ;
423
452
}
424
453
// now that terminals have been restored,
425
454
// attach listeners to update local state when terminals are changed
@@ -437,6 +466,7 @@ export class TerminalService implements ITerminalService {
437
466
let terminalInstance : ITerminalInstance | undefined ;
438
467
let group : ITerminalGroup | undefined ;
439
468
for ( const terminalLayout of terminalLayouts ) {
469
+ this . _mark ( `code/terminal/willRecreateTerminal/${ terminalLayout . terminal ?. id } ` ) ;
440
470
if ( this . _lifecycleService . startupKind !== StartupKind . ReloadedWindow && terminalLayout . terminal ?. type === 'Task' ) {
441
471
continue ;
442
472
}
@@ -457,6 +487,7 @@ export class TerminalService implements ITerminalService {
457
487
location : { parentTerminal : terminalInstance }
458
488
} ) ;
459
489
}
490
+ this . _mark ( `code/terminal/didRecreateTerminal/${ terminalLayout . terminal ?. id } ` ) ;
460
491
}
461
492
const activeInstance = this . instances . find ( t => {
462
493
return t . shellLaunchConfig . attachPersistentProcess ?. id === groupLayout . activePersistentProcessId ;
0 commit comments