Ghosttyの最大メモリリークを特定して修正する
概要
Ghosttyで発生していた大規模なメモリリークの原因と修正内容の解説。
メモリ管理の仕組みと、バグが発生した経緯の説明。
Claude Codeを契機にリークが顕在化した背景。
修正方法と今後の対策についての考察。
再発防止策やコミュニティの貢献への謝辞。
Ghosttyのメモリリーク問題と修正
- 数ヶ月前からGhosttyで極端なメモリ消費の報告が相次いだ事例。
- 一部ユーザーが10日間の稼働で37GB消費を確認。
- 本件の原因究明と修正内容の概要説明。
- Ghostty 1.0以降から存在したバグだが、Claude CodeなどのCLIアプリにより顕在化。
- 修正済みであり、nightlyリリースや1.3タグにて提供予定。
Ghosttyのメモリ管理構造
- PageListというデータ構造で端末内容を管理。
- PageListは双方向リンクリストで、各ノードがページ(文字・スタイル・ハイパーリンク等)を保持。
- ページは標準サイズと非標準サイズの2種類。
- 標準ページ:プールから取得・解放時はプールに戻す
- 非標準ページ:直接mmapで確保・解放時はmunmap呼び出し
- mmapの頻繁な呼び出しを避けるため、メモリプールを活用。
スクロールバック最適化とバグの発生
- スクロールバック制限に達すると、最古のページを再利用する最適化を実装。
- 再利用時、メタデータのみ標準サイズにリセットし、実際のメモリは非標準のまま残存。
- 解放時、標準ページと誤認しmunmapが呼ばれず、メモリリーク発生。
- 非標準ページは本来稀だが、Claude Codeの出力仕様で大量発生。
修正内容
- 非標準ページは再利用せず、解放時に必ずmunmapを実行。
- スクロールバック時に非標準ページを検出した場合は、新規標準ページをプールから取得。
- macOS向けに仮想メモリタグを導入し、PageListのメモリを特定しやすく改善。
再発防止策
- Zigのリーク検出アロケータをデバッグビルド・ユニットテストで利用。
- ValgrindやmacOS InstrumentsでGUIやGTKパスも検証。
- 今回のリーク再現用のテストケースを新規追加。
- 再現性のあるバグ報告が修正の鍵。
コミュニティへの謝辞
- @grishyによる再現手順の提供と分析への感謝。
- 詳細な診断を行ったコミュニティメンバーへの謝意。
- PageListが問題箇所であることを特定するための重要なヒントの提供。
Ghosttyの今後のメモリ管理戦略
- 現在は標準ページを基本とし、最適化・単純化を優先。
- 非標準ページの再利用や動的調整は今後の課題として検討。
- より複雑な戦略(利用頻度に応じた調整等)は追加調査後に検討予定。
まとめ
- Ghostty史上最大級のメモリリークが修正された事例。
- 今後もメモリ関連の報告を注視し、再現性のある問題には迅速に対応予定。
- コミュニティの協力がバグ修正の大きな原動力となった事例。