Skip to content

Remove ugly throttling mechanism when pasting to the terminal #283056

@Tyriar

Description

@Tyriar

@Jarred-Sumner pointed out in https://x.com/jarredsumner/status/1999317065237512224 this throttling mechanism on paste/sendText (my response at https://x.com/Tyriar/status/1999487637674147925):

input(data: string, isBinary: boolean = false): void {
if (this._store.isDisposed || !this._ptyProcess) {
return;
}
this._writeQueue.push(...chunkInput(data).map(e => {
return { isBinary, data: e };
}));
this._startWrite();
}

private _startWrite(): void {
// Don't write if it's already queued of is there is nothing to write
if (this._writeTimeout !== undefined || this._writeQueue.length === 0) {
return;
}
this._doWrite();
// Don't queue more writes if the queue is empty
if (this._writeQueue.length === 0) {
this._writeTimeout = undefined;
return;
}
// Queue the next write
this._writeTimeout = setTimeout(() => {
this._writeTimeout = undefined;
this._startWrite();
}, Constants.WriteInterval);
}

const enum Constants {
/**
* Writing large amounts of data can be corrupted for some reason, after looking into this is
* appears to be a race condition around writing to the FD which may be based on how powerful
* the hardware is. The workaround for this is to space out when large amounts of data is being
* written to the terminal. See https://github.com/microsoft/vscode/issues/38137
*/
WriteMaxChunkSize = 50,
}
/**
* Splits incoming pty data into chunks to try prevent data corruption that could occur when pasting
* large amounts of data.
*/
export function chunkInput(data: string): string[] {
const chunks: string[] = [];
let nextChunkStartIndex = 0;
for (let i = 0; i < data.length - 1; i++) {
if (
// If the max chunk size is reached
i - nextChunkStartIndex + 1 >= Constants.WriteMaxChunkSize ||
// If the next character is ESC, send the pending data to avoid splitting the escape
// sequence.
data[i + 1] === '\x1b'
) {
chunks.push(data.substring(nextChunkStartIndex, i + 1));
nextChunkStartIndex = i + 1;
// Skip the next character as the chunk would be a single character
i++;
}
}
// Push final chunk
if (nextChunkStartIndex !== data.length) {
chunks.push(data.substring(nextChunkStartIndex));
}
return chunks;
}

This was added as one of the attempts to try fix an issue where sending large amounts of data to the terminal would drop chunks of it #38137

This comment is the most relevant explanation as to why I thought this was happening at the time. I believe I was also never able to reproduce the problem on my machine:

const enum Constants {
/**
* Writing large amounts of data can be corrupted for some reason, after looking into this is
* appears to be a race condition around writing to the FD which may be based on how powerful
* the hardware is. The workaround for this is to space out when large amounts of data is being
* written to the terminal. See https://github.com/microsoft/vscode/issues/38137
*/
WriteMaxChunkSize = 50,
}

The justification for the original fix is that correctness is much more important than performance here as pasting large amounts of data like this is an edge case, at least in a terminal within an editor. It sucks though so we should fix it.

Metadata

Metadata

Labels

feature-requestRequest for new features or functionalityimportantIssue identified as high-priorityinsiders-releasedPatch has been released in VS Code Insidersterminal-processProblems launching processes, managing ptys, exiting, process leaks, etc.

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions