【何が起きたか】GitHub Copilot appにおける超巨大PRの高速描画達成

GitHubはデスクトップ環境向けに「GitHub Copilot app」を提供しています。本アプリは2026年6月17日にmacOS、Windows、Linux向けに一般提供されました[1]。その後、同年7月7日にはCopilot Freeを含む全プランへと対象が拡大されました[1]。企業向けのBusinessやEnterpriseプランでは専用ポリシーによる管理が可能です[1]。

本アプリにはプルリクエスト(PR:変更コードのレビューと統合を依頼するGitHubの機能)の管理画面が備わっています。開発者はPRの概要やCI(継続的インテグレーション:自動テストやビルドを行う仕組み)の状況を確認できます[2]。「Files changed」タブで差分を確認し、コメント投稿やAIエージェント(目的に沿って複数の手順を実行するAI機能)への修正依頼を行えます[2]。

GitHubは本画面において、超大規模な差分とレビュー会話の高速描画を達成したと公表しました[3]。検証には同社が確認した中で最大のオープンソースPRが用いられました[4]。その規模は2,200ファイル、100万行を超える変更行数、400件超のインラインレビューコメントを含みます[3, 4, 5, 6]。

同社は検証結果として、本PRが通常サイズのように開いてスクロールできたと報告しました[7]。ただし、これは開閉やスクロール時の挙動に関する定性的な評価です[7]。通常サイズのPRを対照群にした定量的な速度比較ではありません[7]。また、本改善は既存のレビュー会話や差分の描画処理を効率化したものです[8]。AIがコードを自動解析してレビューコメントを生成する機能自体の改善とは区別されると解釈できます[8, 9]。

測定対象の項目測定値備考
対象PRのファイル数2,200ファイルGitHubが確認した最大のオープンソースPR[3, 4]
変更行数の下限100万行超同一PR内の変更行数の合計値[4, 5]
インラインレビューコメント数の下限400件超差分コード行に直接投稿されたコメント総数[4, 6]

後輩2,200ファイルのPRを滑らかに動かしたと聞くと、AIがレビューを高速に自動生成してくれる機能の話かと思っちゃいますね。

先輩そこは混同しやすい部分だね。公式記事は差分と既存レビュー会話の表示・データ供給を扱っていて、フロントエンド(画面側の処理)のUI(ユーザインタフェース)描画の最適化であり、AIによるレビュー生成機能の改善を示す内容ではないと読めるよ。

後輩コードを生成するモデルの話ではなく、大量の差分とコメントを画面に表示する描画技術なんですね。

先輩そうなんだ。どれだけ優れたAI機能があっても、100万行の差分を開いた瞬間に画面が固まってはレビュー作業が成立しないからね。

【なぜ今か】分割困難な大規模PRの存在と従来の仮想スクロールが抱える壁

ソフトウェア開発では、変更内容を小さく分割してレビューすることが推奨されます。しかし、大規模なリファクタリングや移行作業では、全体をひとつの変更として取り込まなければならない場合があります[10]。きれいに分割できない作業では、単一の巨大なPRになり得るとGitHubは説明しています[10]。

GitHubは関心事ごとにブランチを積み重ねてレビューする「stacked PR」を肯定しています[11, 12]。分割可能な作業はstacked PRで層を分ける一方、分割が困難な変更は強固な表示性能で支えるという使い分けが合理的であると解釈できます[11]。ただし、今回の表示改善だけを根拠に、分割可能な変更を巨大PRにまとめてよいとは言えないと解釈できます[12]。

Webフロントエンドで長大なリストを表示する際、仮想スクロール(画面外の要素を描画せず、表示領域付近のみを描画して負荷を抑える技術)が広く用いられます。コード差分のみを扱う仮想化では、各コード行の高さが描画前に確定しています[13]。ブラウザは事前に行位置やスクロール領域を正確に計算できます[13]。

しかし、差分の間にレビューコメントが加わると計算が困難になります[14]。コメントの高さはMarkdown(見出しやリンクなどを記述する軽量な書式)の折り返し、展開状態、返信欄の有無、画像の読み込みなどに左右されます[13, 14]。描画時になるまで正確な寸法は分かりません[13]。

あらかじめ固定の高さを推定して余白を予約する手法も存在します[15]。しかし、推定が大きすぎると不自然な空白が生じます[15]。小さすぎると内容が欠けたり内部スクロールが発生したりします[15]。実測した高さを全体のオフセット表(位置管理テーブル)へ書き戻すと、スクロール中に下の要素が不意に動き、画面位置が跳ぶ「スクロールジャンプ」を引き起こします[15]。

後輩コード行の仮想スクロールは一般的な技術なのに、レビューコメントが入るだけでどうしてそんなに難しくなるんですか?

先輩コード行は文字サイズから高さを事前に計算できるけれど、コメントはMarkdown(見出しやリンクなどを記述する軽量な書式)や画像が含まれて描画するまで正確な高さが分からないからだよ。

後輩高さが分からないなら、適当な推定値で余白を確保しておけばいい気もします。

先輩その推定が外れて実際の高さを反映させた瞬間に、画面全体のスクロール位置がガタッと跳んでしまうんだ。それが最大の壁だったんだね。

【何が変わるか:設計】確定コードと動的コメントを分離する2系統の寸法管理

GitHubはこの課題を解決するため、寸法の管理領域を2つに分離しました[16, 17]。コード行の高さは確定した幾何情報として累積計算を維持します[17]。一方で、コメントや返信欄は「動的ブロック」として独立して管理します[16, 17]。動的ブロックは安定キーを持ち、ファイル、行、左右側へのアンカー(位置の基準点)を保持します[17]。コメントの寸法が変わってもコード行側の幾何情報は再構築されません[17]。

動的ブロックの高さの優先順位は実測値、キャッシュ値(再利用のため一時保存した値)、推定値です[17, 18]。まず初期状態では推定値を用います[17, 18]。次に、識別情報と表示幅が一致するキャッシュ値があればそれを適用します[18]。そしてDOM(HTML要素の木構造データ)の実測値が得られた場合は、実測値を最優先して高さを確定させます[18]。

データ供給の段階でも工夫が施されています。差分は構造データが先に配信され、ファイルツリーやメタデータは読み込み中に先行表示されます[19]。レビューのスレッド全体は小出しにせず、初期側で一括して解決されます[19]。スレッドを先に解決しておくことで、スクロール中にコメント枠が後から挿入される事態を防ぐ意図があると解釈できます[20]。構文ハイライト(コードの構文に応じた色分け)はメインスレッド(UI描画を担う主処理経路)の外で非同期に処理されます[21]。行はまずプレーンテキストで即座に表示され、結果が届き次第着色されます[21]。大きなMarkdown本文や提案変更の文脈も、画面に近づくまで構築されません[22]。

動的ブロックの寸法計測は、スクロールのホットパス(高頻度に実行される処理経路)から除外されています[23]。スクロール中は計測を停止し、表示範囲が落ち着いた後に再開します[23]。計測候補はビューポート(ブラウザの可視表示領域)周辺の約2,400px以内に絞り込まれます[24, 25]。画面から遠いブロックは推定値のまま維持し、近づいた時点で補正して作業量を抑えます[24]。

すでにマウント(実際のDOMに配置)されたコメントは、DOMの実測値を優先してバッチ(一括)で読み取ります[26]。読み取りの間にスタイルの書き込みを挟まない設計により、無駄な再レイアウト(要素の配置や寸法の再計算)や空白を防ぎます[26]。まだマウントされていない近傍コメントは、画面に入る前の予約高さを補正するため、計測パスあたり最大1回だけ画面外描画を行います[25, 27]。ビューポートより高いブロックは画面下に余白が隠れるため、描画計測を省きます[27]。

要素の寸法変化を検知するResizeObserver(要素サイズ監視API)は、通常時は変更フラグを立てるだけに留めます[28]。再計測はアイドル時(ほかの処理がなく、処理が空いている時間)の計測パスに任せます[28]。アンマウント時や非アクティブなPRタブでは監視が解除されます[28]。一方、ユーザーが画面内のコメントを展開したり返信欄を開いたりした場合は、描画前の同じフレーム内で高さを計測して補正します[29]。連続するサイズ変化はフレームあたり最大1回の同期コミット(変更確定)にまとめます[29]。ただし、スクロール操作中はこの同期補正を避け、バッチ計測に回します[29]。

後輩スクロール中には寸法を測らず、止まった後に2,400pxの範囲だけ測るというのは、かなり割り切ったアプローチですね。

先輩その割り切りが重要なんだよ。スクロールの最中にDOMの寸法を測ろうとすると、ブラウザの再計算が頻発して画面がカクつく原因になるからね。

後輩遠くにあるコメントを律儀に正確に測らなくても、ユーザーの視界に入らなければ困らないわけですね。

先輩その通りだよ。確定できるコード行の計算を土台にしつつ、変動するコメントは視界の近くに来たときだけ遅延計測する設計が効いているんだ。

【何が変わるか:体験】閲覧位置を保つアンカー補正とメモリ消費を抑えるキャッシュ戦略

動的ブロックの高さが更新された際、画面表示の位置ずれを防ぐ仕組みがアンカー補正です。GitHubは寸法の更新前に、表示中の行またはブロックの安定した識別子と、その内部オフセット(相対位置)を記録します[30, 31]。寸法更新後に同じ識別子の新しい画面位置を割り出し、スクロール位置を自動補正します[30, 31]。この処理により利用者の閲覧位置が保たれます[30, 31]。

スクロール補正は上下方向で非対称に動作します[32]。ビューポートより上にあるブロックの高さが変化した場合は、差分の分だけスクロール位置を補正します[32]。下方の未表示領域にある変化は補正しません[32]。また、コメント展開や返信欄の起動など利用者が直接操作したブロックでは、上方ブロック由来の補正を抑えて内容を自然に下方へ流します[32]。

スクロール補正の安全機構として、ユーザー操作によるスクロールとプログラムスクロールを厳密に区別しています[33]。ポインター操作やホイールの慣性を妨げることなく、必要な補正漏れを防ぐ設計です[33]。

GitHubは本描画処理の自動検証において、正常と判定する条件を設定しました。コメント間に未充填の隙間がなく、空欄のコメントブロックが存在しないことが求められます[34]。さらに、深いファイルへのスクロールを含む全範囲において、実際のスレッド内容が正常にマウントされていることが確認されます[34]。

大規模な差分文書はメモリ消費が大きいため、長時間のセッションで全訪問分を保持するとメモリを圧迫します[35, 36, 37]。そこでCopilot appは、直近の少数の差分のみをメモリに常駐させ、上限を超える古い文書は退避(破棄)する戦略を採っています[35, 36, 37]。PRへの再訪時はヘッダーやファイルツリーを即座に再表示します[35]。直近の差分キャッシュがあれば画面を即座に復元し、古いキャッシュはバックグラウンドで鮮度を確認します[35]。なお、具体的なキャッシュ保持件数やメモリ使用量の実測値は示されていません[37]。

後輩寸法が変わるたびにスクロール位置をプログラムで直すとなると、ユーザーが指でスクロールしている操作と喧嘩したりしないんですか?

先輩まさにそこが難しい課題だね。だからGitHubはユーザーの手動操作とプログラムによる位置補正を内部で厳密に区別しているんだ。

後輩もしその判定がずれたら、ホイールの慣性が急に止まったり意図しない場所へ飛ばされたりしそうです。

先輩その通りだよ。さらに上の要素が伸びた時だけ補正して、自分がクリックして開いた要素は自然に下へ伸ばすといった細かな配慮で違和感を防いでいるんだね。

【誰に影響するか】開発チームが得られる恩恵とWebエンジニアが実装へ応用する際の留意点

本改善により、日常的にPRをレビューする開発者には表示崩れや中断を防ぐ恩恵が見込めます[38, 39]。超巨大PRであっても通常サイズのように開いてスクロールできます[38]。コメントは枠外への欠けや内部スクロールを伴わず全文が表示されます[38]。折りたたみを展開した際も直下のコードだけが移動し、別画面から戻った際も直前の閲覧位置が保たれます[38]。作業の中断を減らす効果が期待されますが、通常サイズPRとの比較値や秒数・フレームレートでの改善量は確認できません[39]。

Webエンジニアが自らのWebアプリケーション開発に応用できる実践知見として、主に3つの要点が示されています[40]。第1に、事前に確定する幾何情報と描画後に判明する動的ブロックの寸法を分離して管理することです[40]。第2に、DOM読み取りをスクロールのホットパスから外し、画面近傍かつスクロール停止後にバッチ集約することです[40]。第3に、寸法補正時に安定識別子を用いたアンカー補正を行い、表示位置の跳びを防ぐことです[40]。

CI向けの客観的な合否シグナル(テスト予算)の設計も実務の参考になります[41, 43]。検証では、表示中の行・コメント数、1フレームあたり1回の更新にまとまるかとその所要時間、スクロール補正量が検査されます[41]。バックエンドの構造確定後にスクロール中のコメントブロック挿入が0であることや、非表示時の監視解除も合格条件に含まれます[41, 42]。

一方、本知見を評価・導入する際には公表情報の限界に留意する必要があります。GitHub公式記事は各シグナルをテスト予算として説明するものの、個別の予算閾値、具体的な読み込み時間、フレームレート、キャッシュ件数、メモリ使用量の実測値を公表していません[43, 44, 45]。そのため定量的な効果比較は行えません[44]。

また、検証対象はGitHub Copilot app内のPR画面です[46]。ブラウザ版GitHub.comやIDE(コード編集やビルド、デバッグを行う統合開発環境)、Copilotのレビュー生成機能に同じ効果があるとは判断できません[46]。テスト環境はモックサーバ(テスト用の応答を返すサーバ)を用いた記載があるものの、端末スペックやネットワーク条件は明記されておらず再現性比較は限られます[47]。描画が滑らかであってもデータ供給パイプラインが停滞すれば通信待ちが生じるため、通信遅延まで高速化されるとは限らない点にも留意が必要です[48]。

後輩2,200ファイルの超巨大PRでも滑らかに動くなら、もうPRを細かく分割する必要はなくなるんでしょうか?

先輩いや、それは目的を取り違えてはいけないね。本来レビューしやすい単位に小さく分割できるなら、stacked PRなどを使って分けるべきだよ。

後輩あくまで大規模リファクタリングなど、どうしても分割できない変更に直面した時のためのUI技術なんですね。

先輩その通りだよ。そして確定した幾何情報と動的ブロックを分ける設計は、PR画面に限らず複雑なWebアプリを作る私たちエンジニアにとって汎用的な武器になる知見だね。