Skip to content

Performance degradation with large nested documents #1492

@giladacqwiz

Description

@giladacqwiz

Performance degradation with large nested documents (~18 seconds blocking time for mutations)

-- This report was written with help from an AI, that said I am a human 🙃 --

Description

We're experiencing severe performance issues when performing mutations (delete, duplicate, paste) on documents with many pages and nested components. A single delete operation blocks the main thread for ~18 seconds, making the editor unusable for large documents.

Environment

  • Puck version: 0.20.2
  • React version: 19.0.0
  • Node version: 22.16.0
  • Browser: Chrome (latest)
  • OS: macOS

Document Structure

Our documents are PDF-like with:

  • 23 pages (using a custom Page component with type: 'slot')
  • Each page contains 10+ nested components (tables, text blocks, images)
  • ~230 total components across all pages

Performance Analysis

We instrumented the codebase extensively to isolate the bottleneck:

Metric Value % of Total
Total blocking time 17,862ms 100%
Our component render time 42ms (98 renders @ 0.4ms avg) 0.2%
Puck internal processing ~17,820ms 99.8%

Timing Breakdown

Action START:        T+0ms
First component renders complete: T+100ms
                     ↓
         ══════════ 12 SECOND GAP ══════════  ← Puck internals
                     ↓
Second render batch: T+12,100ms
                     ↓
         ══════════ 5 SECOND GAP ══════════   ← Puck internals
                     ↓
Main thread free:    T+17,862ms

Key Finding

99.8% of the time is spent BETWEEN component render batches, not in our component code. Our components render in <1ms each. The blocking time appears to be in Puck's internal state management, likely:

  1. History/undo system - Deep cloning the entire state tree
  2. Zone reconciliation - Processing deeply nested slot structures
  3. Multiple render passes - For selection, overlays, fields, etc.

Reproduction

  1. Create a document with 20+ pages using slot-based Page components
  2. Add 10+ components to each page (tables, text, etc.)
  3. Perform a delete/duplicate/paste operation
  4. Observe the UI freeze for 15-20 seconds

Expected Behavior

Mutations should complete in <500ms for a responsive editing experience.

Actual Behavior

Mutations block the main thread for 15-20 seconds, making the editor unusable for production documents.

Questions

  1. Is there a way to disable or debounce history recording for better performance?
  2. Are there recommended patterns for optimizing deeply nested slot structures?
  3. Is there a performance mode or lazy rendering option we're missing?

Workarounds Attempted

  • ✅ Memoized all custom components with React.memo - No significant improvement
  • ✅ Verified our component render times are <1ms each

We're happy to provide more details or help test potential fixes. This is a critical blocker for our production use case.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions