Skip to content

perf: fix editor lag on large documents (55K+ lines) (#701)#760

Merged
datlechin merged 2 commits intomainfrom
perf/editor-lag-large-documents-701
Apr 15, 2026
Merged

perf: fix editor lag on large documents (55K+ lines) (#701)#760
datlechin merged 2 commits intomainfrom
perf/editor-lag-large-documents-701

Conversation

@datlechin
Copy link
Copy Markdown
Collaborator

Summary

Fixes editor lag when typing in documents with 55K+ lines / 2.6MB+. Root cause: multiple O(n) operations running synchronously on every keystroke.

Changes (6 files)

  • SwiftUI binding debounce (150ms for >500KB) — eliminates 2.6MB String copy per keystroke
  • Windowed completion text — 10KB window instead of full document copy
  • Prefix cap (100 chars) — stale completion context dismissed instantly
  • Skip keyword uppercase for >500KB documents
  • 8 highlight chunks per cycle (up from 2) — full viewport coverage
  • Edit cancellation scoped — only cancel queries, not edits
  • Small query bypass — highlight queries <8KB skip executor queue

Tree-sitter limitation

SQL grammar takes 700-950ms for incremental parse on 2.6MB documents. Highlighting appears 1-2s after typing stops. This is inherent to tree-sitter at this document size.

Test plan

  • Paste 55K line SQL file — typing should be smooth (no lag)
  • Autocomplete works on large documents (windowed text)
  • Syntax highlighting works (delayed but functional)
  • Normal-size documents (<500KB) work identically to before
  • Build succeeds

Closes #701

Root cause: multiple O(n) operations on every keystroke for large
documents — SwiftUI binding writeback (2.6MB String copy), completion
adapter reading full document text, and tree-sitter edit cancellation
preventing highlight queries from completing.

Fixes:
- Debounce SwiftUI text binding writeback (150ms for docs >500KB) to
  eliminate per-keystroke 2.6MB String copy into SwiftUI
- Set isUpdateFromTextView flag to prevent echo loop through
  updateNSViewController on binding writeback
- Read only prefix substring in completionOnCursorMove instead of full
  document — O(prefix_length) vs O(document_length)
- Extract 10KB windowed text in completionSuggestionsRequested instead
  of copying full document
- Cap completion prefix at 100 chars — dismiss stale context that would
  read thousands of characters
- Skip keyword auto-uppercase for documents >500KB to prevent cascade
  edits that double per-keystroke cost
- Increase highlight chunk limit from 2 to 8 per cycle for large
  documents to cover full viewport
- Only cancel highlight queries (.access) on new edits, not pending
  edits — prevents edit starvation that blocks all highlighting
- Small highlight queries (<8KB) bypass executor queue to avoid being
  blocked by pending large parse operations

Limitation: tree-sitter SQL grammar takes 700-950ms for incremental
parse on 2.6MB documents. Syntax highlighting appears 1-2s after typing
stops. This is a tree-sitter performance characteristic, not fixable
without grammar optimization or a regex fallback highlighter.

Closes #701
- Set isUpdateFromTextView immediately (synchronously) before debounce
  Task — prevents SwiftUI from overwriting typed chars during 150ms delay
- Remove unsafe queue bypass for small queries — use executor's sync
  path which acquires the lock properly, fall through to async if busy
- Raise prefix cap from 100 to 500 chars — prevents false dismissal
  after large paste where replacementRange is briefly stale
- Remove double blank line in Highlighter.swift
@datlechin datlechin merged commit 65802d6 into main Apr 15, 2026
2 checks passed
@datlechin datlechin deleted the perf/editor-lag-large-documents-701 branch April 15, 2026 07:45
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.

Editor lags on long queries

1 participant