Skip to main content
fewer
Custom Layout Algorithm: Built for Large Codebases

Custom Layout Algorithm: Built for Large Codebases

· Yash Srivastava

How we replaced Dagre with a custom Reingold-Tilford tree layout to handle large graphs for tighter spacing, better hierarchy, async layout for smooth imports.

performancelayoutreleasearchitecture

Version 0.2.3 ships a new layout engine: a custom Reingold-Tilford tree layout with contour matching, designed specifically for directory trees. This replaces Dagre with an in-house implementation tuned for large, complex codebases.

Why Move Away from Dagre?

Dagre works well for small-to-medium trees. But as graphs grow past 1,000 nodes, two problems emerge:

  1. Wide, sparse layouts: Dagre spreads nodes horizontally to avoid overlap, creating sprawling diagrams that don't fit the viewport
  2. Sync blocking: Layout computation happens on the main thread, freezing UI during import

Our custom algorithm addresses both with a layered approach that packs nodes tighter and supports async computation.

What Changed

Custom Reingold-Tilford Algorithm

The new algorithm arranges nodes using the classic Reingold-Tilford tree layout with contour matching: parents centered over their children, with contour-based collision prevention. Result: graphs that are 30-40% more compact vertically and horizontally.

Async Layout

Large directory imports now use requestIdleCallback to compute layout without blocking the UI. A progress indicator shows import status.

Sync Fallback

Relayout operations (direction changes, beautify) still use synchronous layout for immediate feedback. The async path only applies to initial import.

Performance Impact

MetricDagreCustom
1K nodes layout time800ms600ms
5K nodes layout time4.2s1.8s
10K nodes layout timeOOM3.5s
Average node spacing50px35px

The custom algorithm handles 10K+ nodes where Dagre runs out of memory.

Migration Notes

If you have saved JSON exports from older versions, they still import correctly. The layout engine is chosen at runtime, not persisted.

Future Improvements

  • Layer-by-layer progressive rendering during async layout
  • Incremental relayout (only recompute affected subtree)
  • Custom edge routing algorithms (orthogonal, spline)