AI Briefing
KO

The rocky road to making diff lines high-performance

·2026.04.04 01:00

Key point

GitHub redesigned diff lines to cut a 1GB heap and 400,000 DOM nodes in large PRs.

1 / 2

Details

GitHub rebuilt the Files changed tab on React, focusing on keeping the review experience fast and stable even on large pull requests. In the worst case, the problems included exceeding 1GB of JavaScript heap, over 400,000 DOM nodes, slow interactions, and high INP.

The core solution wasn't a single fix but a series of optimizations across multiple fronts.

  • Simplifying the v1 diff line structure: the unified view used about 10 DOM elements per line, and the split view used about 15 DOM elements; at the React level, the unified view needed at least 8 components and the split view at least 13 components.
  • Reducing component structure: in v2, dedicated components were separated for split/unified to reduce nested wrappers, cutting a single diff line from 8 components down to about 2.
  • Simplifying event handling: instead of events scattered across multiple child components, a single handler at a higher level now processes them by looking at data-attribute.
  • Moving state and optimizing lookups: comment and context menu state was moved into conditionally rendered child components, useEffect usage was restricted to the top level, and lookups were switched to a Map-based O(1) structure.

Even small changes added up to a large cumulative effect. For example, removing an unnecessary <code> tag from the line number cell eliminated 20,000 DOM nodes for a 10,000-line case. In the same test, v2 compared to v1 improved total component renders from ~183,504 to ~50,004, memory from ~150-250MB to ~80-120MB, and INP from ~450ms to ~100ms.

For the largest PRs, window virtualization was introduced. Using TanStack Virtual to keep only the visible portion in the DOM reduced JavaScript heap and DOM nodes by 10x for p95+ pull requests, and lowered INP from 275–700+ ms to 40–80 ms.

Beyond that, additional improvements — reducing re-renders, removing heavy CSS selectors like :has(...), switching drag/resize to GPU transforms, interaction-level INP tracking with diff-size breakdowns, a Datadog dashboard including memory tagging, server rendering improvements that hydrate only visible diff lines, and progressive diff loading with background fetching — together lowered responsiveness issues and memory pressure across large PRs overall.

This summary was generated automatically by AI. Check the original for the author's claims and context. Copyright belongs to the original author.

Our guide explains how the AI works. Report summary errors, attribution issues, or removal requests via Contact.