Skip to content

Optimizing _doRemoveCustomLineHeight#299793

Open
aiday-mar wants to merge 4 commits intomainfrom
available-sturgeon
Open

Optimizing _doRemoveCustomLineHeight#299793
aiday-mar wants to merge 4 commits intomainfrom
available-sturgeon

Conversation

@aiday-mar
Copy link
Contributor

@aiday-mar aiday-mar commented Mar 6, 2026

fixes #298719

I added date.now() around the commit call, and with this PR, the commit reduces to:

  • 6ms
  • 4ms
  • 2ms

Without this PR, the commit call takes:

  • 154ms
  • 160ms
  • 149ms

Copilot AI review requested due to automatic review settings March 6, 2026 15:57
@aiday-mar aiday-mar self-assigned this Mar 6, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR targets performance of the editor’s LineHeightsManager by reducing the cost of removing staged custom line-height updates, addressing jank when many custom line heights are present (issue #298719).

Changes:

  • Introduces _stagedDecorationIdToLines to avoid O(n) scans/splices when removing staged inserts for a decoration.
  • Switches staged-removal behavior from array splicing to marking staged CustomLine entries as deleted and skipping them during flush.
  • Adds timing console.log instrumentation around commit/flush (appears to be debug instrumentation).
Comments suppressed due to low confidence (2)

src/vs/editor/common/viewLayout/lineHeights.ts:225

  • _flushStagedDecorationChanges can enter an effectively infinite loop when stagedInserts contains only entries marked deleted. In that case the insertion loop skips everything, _invalidIndex remains Infinity, and the subsequent for (let i = 0; i < this._invalidIndex; i++) never terminates (and will also read past _orderedCustomLines). Consider short-circuiting after processing stagedInserts when _invalidIndex is still Infinity (i.e. no actual inserts/deletes affected the ordered array).
	private _flushStagedDecorationChanges(stagedInserts: CustomLine[]): void {
		if (stagedInserts.length === 0 && this._invalidIndex === Infinity) {
			return;
		}
		const flushStart = Date.now();
		for (const pendingChange of stagedInserts) {
			if (pendingChange.deleted) {
				continue;
			}
			const candidateInsertionIndex = this._binarySearchOverOrderedCustomLinesArray(pendingChange.lineNumber);
			const insertionIndex = candidateInsertionIndex >= 0 ? candidateInsertionIndex : -(candidateInsertionIndex + 1);
			this._orderedCustomLines.splice(insertionIndex, 0, pendingChange);
			this._invalidIndex = Math.min(this._invalidIndex, insertionIndex);
		}
		stagedInserts.length = 0;
		this._stagedDecorationIdToLines.clear();
		const newDecorationIDToSpecialLine = new ArrayMap<string, CustomLine>();
		const newOrderedSpecialLines: CustomLine[] = [];

		for (let i = 0; i < this._invalidIndex; i++) {
			const customLine = this._orderedCustomLines[i];
			newOrderedSpecialLines.push(customLine);
			newDecorationIDToSpecialLine.add(customLine.decorationId, customLine);
		}

src/vs/editor/common/viewLayout/lineHeights.ts:174

  • _doRemoveCustomLineHeight no longer uses the stagedInserts parameter. To avoid confusion (and potential lint noise), consider removing the parameter and updating call sites, or renaming it to _stagedInserts if it must remain for signature compatibility.
	private _doRemoveCustomLineHeight(decorationID: string, stagedInserts: CustomLine[]): void {
		const customLines = this._decorationIDToCustomLine.get(decorationID);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Initializing LineHeights is slow when having many custom line heights

2 participants