Skip to content

Speed up large selection deletes#107

Merged
krzyzanowskim merged 1 commit intokrzyzanowskim:mainfrom
brandonbloom:perf/large-selection-delete
Mar 20, 2026
Merged

Speed up large selection deletes#107
krzyzanowskim merged 1 commit intokrzyzanowskim:mainfrom
brandonbloom:perf/large-selection-delete

Conversation

@brandonbloom
Copy link
Copy Markdown
Contributor

Doing select-all + delete in the Ode to STTextView in the example Text Editor was beach balling badly for a few seconds on my machine. This fix speeds it up dramatically.

Sampling showed deleteBackward spending most of its time materializing the deleted text for the yank ring through NSTextLayoutManager.substring(in:). For a large selection, that walks the range through TextKit substring enumeration before the actual deletion happens.

Use the backing attributed string from NSTextContentStorage to read the deleted text directly by NSRange instead. This keeps yank behavior intact without paying the layout-manager substring cost on every large delete.

The existing undo coverage now includes delete-then-yank so the fast path is still checked against the expected deleted text.

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Mar 14, 2026

CLA assistant check
All committers have signed the CLA.

Sampling showed deleteBackward spending most of its time materializing the
deleted text for the yank ring through NSTextLayoutManager.substring(in:).
For a large selection, that walks the range through TextKit substring
enumeration before the actual deletion happens.

Use the backing attributed string from NSTextContentStorage to read the
deleted text directly by NSRange instead. This keeps yank behavior intact
without paying the layout-manager substring cost on every large delete.

The existing undo coverage now includes delete-then-yank so the fast path is
still checked against the expected deleted text.
@brandonbloom brandonbloom force-pushed the perf/large-selection-delete branch from b7247f9 to c948c61 Compare March 14, 2026 20:26
Comment on lines -44 to +45
updateSelectedRangeHighlight()
updateSelectedLineHighlight()
layoutGutter()
setNeedsLayoutSafe()
needsDisplay = true
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

was that intentional part of the change?

@krzyzanowskim krzyzanowskim merged commit d08a18f into krzyzanowskim:main Mar 20, 2026
3 checks passed
krzyzanowskim added a commit that referenced this pull request Mar 20, 2026
- Add TextKit2 viewport/layout convergence, safe relayout, and post-layout
  selection scroll handling
- Fix viewport bounds calc, gutter offset/width issues, and ensure viewport
  range layout
- Track speech state via AVSpeechSynthesizer delegate; validate Stop Speaking
- Improve large selection delete performance (#107)
- Resolve NavigationSplitView crash (#102); add ignoresSafeArea; reset typing
  attributes and introduce resetTypingAttributes()
- Fix sizeToFit() gutter width handling (#101)
- Major accessibility improvements (VoiceOver, selection, scrolling, traits,
  notifications) in 2.3.3
- Adjust layout fragment height handling (2.3.2)
- Color/appearance and typing attribute updates (2.3.1)
- Rework 2.3.0 section: consolidate features, fixes, refactors, and tests
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.

3 participants