Skip to content

Commit 7e64a96

Browse files
committed
refactor(diff): optimize streaming performance with chunk-based updates
Replace line-by-line diff calculation with optimized chunk-based streaming for better performance with large files. Instead of processing each line individually, content is now updated in dynamic chunks (max(50, totalLines/20)) with a 10ms delay between updates for smooth visualization. Key improvements: Replace individual line inserts with efficient bulk content updates Reduce scroll jitter by only updating viewport when needed Optimize decoration updates to align with chunk processing Keep cursor at document start to avoid streaming interference These changes significantly improve the performance and visual experience of the diff view, particularly when handling larger files or rapid content updates.
1 parent 2de2f65 commit 7e64a96

File tree

1 file changed

+29
-24
lines changed

1 file changed

+29
-24
lines changed

src/integrations/editor/DiffViewProvider.ts

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -95,33 +95,38 @@ export class DiffViewProvider {
9595
throw new Error("User closed text editor, unable to edit file...")
9696
}
9797

98-
// Calculate the diff between streamed lines and accumulated lines
99-
const diffs = diff.diffLines(this.streamedLines.join("\n"), accumulatedLines.join("\n"))
100-
let currentLine = 0
98+
const diffLines = accumulatedLines.slice(this.streamedLines.length)
10199

102-
// Place cursor at the beginning of the diff editor
100+
// Place cursor at the beginning of the diff editor to keep it out of the way of the stream animation
103101
const beginningOfDocument = new vscode.Position(0, 0)
104102
diffEditor.selection = new vscode.Selection(beginningOfDocument, beginningOfDocument)
105103

106-
// Apply changes and update decorations only for changed sections
107-
for (const part of diffs) {
108-
if (part.added) {
109-
const edit = new vscode.WorkspaceEdit()
110-
const lines = part.value.split("\n")
111-
const contentToAdd = part.value.endsWith("\n") ? part.value : part.value + "\n"
112-
edit.insert(document.uri, new vscode.Position(currentLine, 0), contentToAdd)
113-
await vscode.workspace.applyEdit(edit)
104+
// Calculate chunk size based on total lines
105+
const totalLines = accumulatedLines.length
106+
const chunkSize = Math.max(50, Math.floor(totalLines / 20)) // Process ~20 chunks total
107+
const totalChunks = Math.ceil(diffLines.length / chunkSize)
108+
const delayPerChunk = 10 // 10ms between chunks
114109

115-
// Update decorations for the changed section
116-
for (let i = 0; i < lines.length; i++) {
117-
this.activeLineController.setActiveLine(currentLine + i)
118-
this.fadedOverlayController.updateOverlayAfterLine(currentLine + i, document.lineCount)
119-
}
120-
// Scroll to the first line of the changed section
121-
this.scrollEditorToLine(currentLine)
122-
currentLine += lines.length
123-
} else if (!part.removed) {
124-
currentLine += part.count || 0
110+
for (let chunk = 0; chunk < totalChunks; chunk++) {
111+
const startIdx = chunk * chunkSize
112+
const endIdx = Math.min(startIdx + chunkSize, diffLines.length)
113+
const currentLine = this.streamedLines.length + endIdx
114+
115+
// Replace content up to current chunk
116+
const edit = new vscode.WorkspaceEdit()
117+
const rangeToReplace = new vscode.Range(0, 0, currentLine, 0)
118+
const contentToReplace = accumulatedLines.slice(0, this.streamedLines.length + endIdx).join("\n") + "\n"
119+
edit.replace(document.uri, rangeToReplace, contentToReplace)
120+
await vscode.workspace.applyEdit(edit)
121+
122+
// Update decorations and scroll less frequently
123+
this.activeLineController.setActiveLine(currentLine)
124+
this.fadedOverlayController.updateOverlayAfterLine(currentLine, document.lineCount)
125+
this.scrollEditorToLine(currentLine)
126+
127+
if (chunk < totalChunks - 1) {
128+
// Don't delay on last chunk
129+
await new Promise((resolve) => setTimeout(resolve, delayPerChunk))
125130
}
126131
}
127132

@@ -360,10 +365,10 @@ export class DiffViewProvider {
360365

361366
private scrollEditorToLine(line: number) {
362367
if (this.activeDiffEditor) {
363-
const scrollLine = line + 4
368+
const scrollLine = line + 2 // Reduced offset for smoother appearance
364369
this.activeDiffEditor.revealRange(
365370
new vscode.Range(scrollLine, 0, scrollLine, 0),
366-
vscode.TextEditorRevealType.InCenter,
371+
vscode.TextEditorRevealType.InCenterIfOutsideViewport, // Changed to only scroll if needed
367372
)
368373
}
369374
}

0 commit comments

Comments
 (0)