Skip to content

Commit 45d885e

Browse files
committed
Debounce data events to shellIntegration API
This will greatly improve performance when running commands with large output and also enables the feature for remote terminals. Part of microsoft#145234
1 parent 3b3e8c2 commit 45d885e

File tree

3 files changed

+23
-14
lines changed

3 files changed

+23
-14
lines changed

src/vs/workbench/api/browser/mainThreadTerminalShellIntegration.ts

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

66
import { Event } from 'vs/base/common/event';
7-
import { Disposable } from 'vs/base/common/lifecycle';
7+
import { Disposable, toDisposable, type IDisposable } from 'vs/base/common/lifecycle';
88
import { URI } from 'vs/base/common/uri';
99
import { TerminalCapability, type ITerminalCommand } from 'vs/platform/terminal/common/capabilities/capabilities';
1010
import { ExtHostContext, MainContext, type ExtHostTerminalShellIntegrationShape, type MainThreadTerminalShellIntegrationShape } from 'vs/workbench/api/common/extHost.protocol';
@@ -26,6 +26,13 @@ export class MainThreadTerminalShellIntegration extends Disposable implements Ma
2626

2727
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostTerminalShellIntegration);
2828

29+
const instanceDataListeners: Map<number, IDisposable> = new Map();
30+
this._register(toDisposable(() => {
31+
for (const listener of instanceDataListeners.values()) {
32+
listener.dispose();
33+
}
34+
}));
35+
2936
// onDidChangeTerminalShellIntegration
3037
const onDidAddCommandDetection = this._store.add(this._terminalService.createOnInstanceEvent(instance => {
3138
return Event.map(
@@ -47,14 +54,22 @@ export class MainThreadTerminalShellIntegration extends Disposable implements Ma
4754
}
4855
// String paths are not exposed in the extension API
4956
currentCommand = e.data;
50-
this._proxy.$shellExecutionStart(e.instance.instanceId, e.data.command, convertToExtHostCommandLineConfidence(e.data), e.data.isTrusted, this._convertCwdToUri(e.data.cwd));
57+
const instanceId = e.instance.instanceId;
58+
this._proxy.$shellExecutionStart(instanceId, e.data.command, convertToExtHostCommandLineConfidence(e.data), e.data.isTrusted, this._convertCwdToUri(e.data.cwd));
59+
60+
// TerminalShellExecution.createDataStream
61+
// Debounce events to reduce the message count - when this listener is disposed the events will be flushed
62+
instanceDataListeners.get(instanceId)?.dispose();
63+
instanceDataListeners.set(instanceId, Event.accumulate(e.instance.onData, 50, this._store)(events => this._proxy.$shellExecutionData(instanceId, events.join())));
5164
}));
5265

5366
// onDidEndTerminalShellExecution
5467
const commandDetectionEndEvent = this._store.add(this._terminalService.createOnInstanceCapabilityEvent(TerminalCapability.CommandDetection, e => e.onCommandFinished));
5568
this._store.add(commandDetectionEndEvent.event(e => {
5669
currentCommand = undefined;
57-
this._proxy.$shellExecutionEnd(e.instance.instanceId, e.data.command, convertToExtHostCommandLineConfidence(e.data), e.data.isTrusted, e.data.exitCode);
70+
const instanceId = e.instance.instanceId;
71+
instanceDataListeners.get(instanceId)?.dispose();
72+
this._proxy.$shellExecutionEnd(instanceId, e.data.command, convertToExtHostCommandLineConfidence(e.data), e.data.isTrusted, e.data.exitCode);
5873
}));
5974

6075
// onDidChangeTerminalShellIntegration via cwd
@@ -65,12 +80,6 @@ export class MainThreadTerminalShellIntegration extends Disposable implements Ma
6580

6681
// Clean up after dispose
6782
this._store.add(this._terminalService.onDidDisposeInstance(e => this._proxy.$closeTerminal(e.instanceId)));
68-
69-
// TerminalShellExecution.createDataStream
70-
// TODO: Support this on remote; it should go via the server
71-
if (!workbenchEnvironmentService.remoteAuthority) {
72-
this._store.add(this._terminalService.onAnyInstanceData(e => this._proxy.$shellExecutionData(e.instance.instanceId, e.data)));
73-
}
7483
}
7584

7685
$executeCommand(terminalId: number, commandLine: string): void {

src/vs/workbench/api/common/extHostTerminalShellIntegration.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,12 @@ export class ExtHostTerminalShellIntegration extends Disposable implements IExtH
6262
// console.log('*** onDidStartTerminalShellExecution', e);
6363
// // new Promise<void>(r => {
6464
// // (async () => {
65-
// // for await (const d of e.createDataStream()) {
65+
// // for await (const d of e.read()) {
6666
// // console.log('data2', d);
6767
// // }
6868
// // })();
6969
// // });
70-
// for await (const d of e.createDataStream()) {
70+
// for await (const d of e.execution.read()) {
7171
// console.log('data', d);
7272
// }
7373
// });

src/vscode-dts/vscode.proposed.terminalShellIntegration.d.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@ declare module 'vscode' {
4646

4747
/**
4848
* Creates a stream of raw data (including escape sequences) that is written to the
49-
* terminal. This will only include data that was written after `readData` was called for
50-
* the first time, ie. you must call `readData` immediately after the command is executed
51-
* via {@link TerminalShellIntegration.executeCommand} or
49+
* terminal. This will only include data that was written after `read` was called for
50+
* the first time, ie. you must call `read` immediately after the command is executed via
51+
* {@link TerminalShellIntegration.executeCommand} or
5252
* {@link window.onDidStartTerminalShellExecution} to not miss any data.
5353
*
5454
* @example

0 commit comments

Comments
 (0)