Skip to content

perf: wrap EditDelta.new_lines in Arc to avoid deep-cloning styled blocks#11631

Draft
warp-dev-github-integration[bot] wants to merge 1 commit into
masterfrom
oz/memory-fix-arc-edit-delta-new-lines
Draft

perf: wrap EditDelta.new_lines in Arc to avoid deep-cloning styled blocks#11631
warp-dev-github-integration[bot] wants to merge 1 commit into
masterfrom
oz/memory-fix-arc-edit-delta-new-lines

Conversation

@warp-dev-github-integration
Copy link
Copy Markdown

Summary

Fixes excessive memory usage detected by Sentry issue #7259255054 (82 events, mac_stable_release / mac_preview_release).

Root Cause

The EditDelta struct's new_lines field (Vec<StyledBufferBlock>) was being deep-cloned every time a content-change event was forwarded to the render pipeline. For large files loaded via Buffer::replace_all, this vector contains all styled blocks for the entire file content.

Heap profile analysis showed ~7 GB total in-use memory with the following top allocators:

  • 41.1% (3 GB)Buffer::replace_all → SumTree append_str (buffer text replacement)
  • 24.7% (1.8 GB)Vec<StyledBufferBlock>::clone() in CodeEditorModel::handle_content_model_event
  • 16.4% (1.2 GB) — Tree-sitter parsing

Changes

  1. Wrap EditDelta.new_lines in Arc<Vec<StyledBufferBlock>> — Cloning an EditDelta now bumps a reference count (O(1)) instead of deep-copying every styled block
  2. Use Arc::try_unwrap in layout_delta() — When the layout pipeline consumes the delta (typically the sole owner), it unwraps without cloning; falls back to clone only if there are multiple references
  3. Remove unnecessary delta.clone() in DelayRendering::flush_render — The delta was already owned from a consuming iterator, making the clone redundant
  4. Update all construction sites to wrap in Arc::new()
  5. Update test assertions to dereference Arc for comparisons

Expected Impact

  • Eliminates ~1.8 GB of unnecessary allocations per large file load event (the Vec<StyledBufferBlock>::clone path)
  • Reduces memory pressure from the flush_render code path (additional unnecessary clone removed)

Testing

  • Updated 99 test assertions in buffer_tests.rs to work with the Arc wrapper
  • All existing test logic preserved (only dereference operator added)

CHANGELOG-IMPROVEMENT:
CHANGELOG-BUG-FIX:
CHANGELOG-NEW-FEATURE:
CHANGELOG-IMAGE:

Conversation: https://staging.warp.dev/conversation/5505471b-acef-408a-92f0-799b1dc2186c
Run: https://oz.staging.warp.dev/runs/019e5971-7b78-7e2a-9e82-b127458e0218
This PR was generated with Oz.

…ocks

The EditDelta struct's new_lines field (Vec<StyledBufferBlock>) was being
deep-cloned every time a content-change event was forwarded to the render
pipeline. For large files loaded via Buffer::replace_all, this vector
contains all styled blocks for the entire file content, causing ~1.8 GB
of unnecessary allocations (24.7% of 7 GB total in-use memory from Sentry
issue #7259255054).

Changes:
- Wrap EditDelta.new_lines in Arc<Vec<StyledBufferBlock>> so clones are
  reference-counted (O(1)) instead of deep-copying every styled block
- Use Arc::try_unwrap in layout_delta() to avoid cloning when the Arc
  has a single owner (the common case in the layout pipeline)
- Remove unnecessary delta.clone() in DelayRendering::flush_render where
  the delta was already owned from a consuming iterator
- Update all construction sites to wrap in Arc::new()
- Update test assertions to dereference Arc for comparisons

Co-Authored-By: Oz <oz-agent@warp.dev>
@cla-bot cla-bot Bot added the cla-signed label May 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant