Deferred Optimizations

Performance optimizations that were considered but intentionally not implemented, because the complexity they add outweighs their benefit at the data sizes this fork targets — and the project explicitly values code that stays readable and understandable at a human level.

Why this file exists: so the trade-offs are recorded rather than rediscovered. If a real workload outgrows the current approach, start here. Each entry notes the expected gain, the complexity cost, and the trigger that would justify doing it.

Rendering & layout

Visible-only / incremental stacking

_recalculateStacking() runs over every item on each pan/zoom (~8ms at 10k items, measured in the test suite). It could instead stack only items overlapping the viewport, and cache row assignments so a pan that reveals new items appends rather than recomputes.
Gain: High at 100k+ items · Cost: High — invalidation logic, edge cases around fixed group heights, and the "stable rows during drag" guarantee all get harder. Trigger: continuous pan drops below 60fps on the real dataset. Mitigated already: stacking no longer runs per-frame during a drag (rows are frozen until drop).

Spatial index for hit-testing & culling

Hit-testing and _updateVisibleItems() are linear scans over all items. An interval tree or a bucketed index keyed by time would make both O(log n + k). Items are already sorted by start, so a binary search plus a "max end so far" augmentation would get most of the win cheaply.
Gain: Medium · Cost: Medium — an index to keep in sync on every add/update/remove/edit. Trigger: hover/click latency becomes noticeable, or visible-set computation dominates a frame.

Layer caching for static canvases

The axis, group-label panel, and minimap are redrawn on every frame even when only the body changed (e.g. item hover). They could be cached to offscreen canvases and only repainted when their inputs change (window, groups, theme, yOffset).
Gain: Medium on hover-heavy use · Cost: Medium — dirty-flag bookkeeping per layer. Trigger: profiling shows label/axis/minimap repaint is a meaningful share of frame time.

Dirty-rectangle / partial redraw

Today every frame clears and repaints the whole body. Tracking dirty regions (only the rows/columns that changed) would cut fill cost on large canvases.
Gain: Medium · Cost: High — bookkeeping touches every draw path and is a classic source of "ghost" artifacts. Trigger: very large canvases (4K, tall timelines) where clear+repaint is itself expensive.

Glyph / text atlas for item labels

Item text is drawn with fillText each frame (widths are cached, the raster is not). Pre-rendering labels to an offscreen atlas and blitting would help when thousands of items are on screen with stable text.
Gain: Medium at high visible counts · Cost: High — atlas allocation/eviction, DPR and font-change invalidation, and it largely duplicates what the browser already caches. Trigger: text fill shows up hot in a profile with many visible items.

Concurrency & scheduling

Stacking in a Web Worker

Move _recalculateStacking / _computeFixedGroupHeights off the main thread for very large datasets.
Gain: Medium (keeps the main thread free) · Cost: High — serialization, async layout, and races with live edits. Trigger: layout work alone exceeds a frame budget and cannot be reduced by visible-only stacking first.

rAF-aligned follow-now

Follow-now uses a 1s setInterval. A requestAnimationFrame loop would be smoother and naturally pause with the tab.
Gain: Low · Cost: Low — but unnecessary today. Already mitigated: the tick is skipped while document.hidden. Trigger: sub-second follow smoothness is required.

Correctness-adjacent (complexity, not just speed)

Calendar-aware / DST-correct axis stepping

Grid ticks step by fixed millisecond intervals, so DST transitions and month/year boundaries can land slightly off a clean local label. Proper stepping walks a calendar (variable-length months, DST-aware day boundaries).
Gain: Low (cosmetic for this use case) · Cost: Medium — calendar math is fiddly. Trigger: labels near DST/month boundaries are visibly wrong for the audience.

← Risks & go/no-go · Future ideas → · Demos