Performance
Virtualization
GitGraph virtualizes rows and lane geometry using @tanstack/react-virtual. Only rows in the viewport (plus an overscan band of 8) are mounted; lane edges are clipped to the same window via the gutter's range prop. Memory and DOM-node count stay roughly constant regardless of commit-set size.
Measured worst case
At 10,000 commits with the default rowHeight=40, the Phase 5B spike measured per-browser frame times during a 5-second scripted scroll:
| Browser | max | p99 | p95 | median |
|---|---|---|---|---|
| chromium | 27 ms | 25 ms | 22 ms | 17 ms |
| firefox | 38 ms | 37 ms | 24 ms | 17 ms |
| webkit | 60 ms | 59 ms | 55 ms | 28 ms |
Webkit's 60 ms worst-case is inside one dropped frame at 60 fps and well under the production regression bar of MAX_FRAME_MS = 100 in tests/e2e/graph-virtualization.spec.ts — that ceiling is sized to catch a broken virtualizer (which would produce 200–2000 ms+ frames) without flaking on slow CI.
Tuning rowHeight
Larger rowHeight renders fewer rows per viewport and reduces frame cost roughly linearly. The default of 40 is tuned for a single-line message; bump to 56 if you render a two-line message or larger avatars.
Scenarios that degrade
- Lane count above ~12 produces wide gutters; the SVG is fine but horizontal scroll appears.
- Refs decorations are not virtualized — a single commit with 100+ refs allocates 100+ badge DOM nodes. Practical Git histories don't hit this.
- The window-scroll variant (passing
scrollContainerRefpointing atdocument.documentElement) is slightly more expensive than the default self-scroll layout because it can't observe a single resize boundary.