数百MBのログファイルをエディタにドロップした瞬間にカーソルが虹色になり、アプリがフリーズ。
しばらく待たされた挙句に「読み取り専用で開きました」と言われるか、最悪クラッシュする。
結局、諦めて less と tail -f に戻る――。
Macで開発やインフラ運用をしていれば、誰もが一度は経験するあの「絶望」です。
私が開発している MrEditor は、10GBのログファイルを、虹色を一度も出さずに開いて、
スクロールして、検索して、レビューできるエディタです。まずここが出発点でした。
編集や差分表示(diff)はその後の話であり、**「固まらずに中を見られる」**ことこそが
すべての土台です。
手元の 10.00GB(86,420,337行・日本語UTF-8)の巨大ログを開いたときの実測値がこちらです。
| 項目 | 実測値 |
|---|---|
| 表示開始までの時間 | 45〜80ms(実行ごとに変動、ほぼ一瞬) |
| その間の虹色カーソル | 0回 |
| 10GB開封時のフットプリント | 145MB(空の状態で143MB。開くコストはほぼゼロ) |
| 書き換え可能な実メモリ(Dirty Page) |
0バイト(vmmap の dirty が 0K) |
| 末尾の行へのジャンプ | 一瞬(体感の待ち時間なし) |
| 全文検索(8,600万行対象) | 途中で固まることなく実行可能 |
※ 数値は v1.7 / 2026-07-19 に実機計測(
MREDITOR_TIMING/vmmap、Apple Silicon環境)。
索引(インデックス)の全構築には別途 約10秒かかります(後述)。
なぜ普通のエディタは虹色になるのか
macOSでテキストを扱う標準コンポーネントは NSTextView です。この背後にある
NSTextStorage は「全文をメモリに保持する」設計のため、10GBものファイルを渡せば
当然破綻します。読み込みでフリーズし、メモリを限界まで食いつぶし、虹色が回り出す。
多くのMac用エディタが巨大ファイルでつまずく原因は、ほぼここに集約されます。
つまり、「処理を高速化する」以前に、「全文をメモリに乗せる」という前提そのものを
捨てることが出発点でした。
虹色を出さないための「4つの最小構成」
やっていることは、巨大ログビューアの定石(klogg / glogg / lnav の世界観)を
MacのネイティブUIに持ち込んだだけです。特別な魔法はありません。
-
ファイルは mmap で開く
全文をメモリにコピーせず、OSに「このファイルをアドレス空間にマッピングしてくれ」と
頼むだけ。開いた瞬間に10GBをスキャンする処理自体が存在しないため、そもそも
固まりようがありません。 -
「疎(そ)」な行インデックスを持つ
全行の位置を愚直に記憶するのではなく、2,000行ごとに「行番号 → バイトオフセット」の
ペアを1組だけ記録します。これにより、1億行あってもインデックスはわずか約800KBで
収まります。任意の行へ移動する際は、最寄りのアンカーから少し走査するだけで到達できます。 -
見えている行だけを描画する
画面に映る数十行だけを、その都度ファイルからピンポイントで読み込んで描画します。
100行しか見えていないなら、100行分しか仕事をしません。 -
スクロールは「行」単位の自前計算
10GBのテキストをピクセル換算すると16億ポイントを超え、座標が浮動小数点の精度の壁を
踏んでしまいます。そのため、巨大な仮想ビューは作らず、スクロールバーは「いま何行目に
いるか」をベースに自前で管理しています。
この4つのアプローチにより、「開く」「末尾へ飛ぶ」「スクロールする」のすべてが、
ファイルサイズに依存しない一定の軽さになります。虹色が出る余地そのものを消し去りました。
これで「ログレビュー」が実用レベルになる
閲覧の土台がサイズに関わらず一定に軽いため、その上のレイヤーの操作も軽快なままです。
-
末尾の行へ即ジャンプ:ターミナルで
tailを打ち直す手間が消えます。 - 全文検索・正規表現・フィルタ表示:該当行だけを抜き出す「live grep」が可能です。
-
tail -f追従(⌥⌘F):開いた後に書き込まれた行を、末尾にいる間自動で追います
(その場で編集を始めると追従は一時停止し、保存すると再開します)。 - 構造化表示:CSV/TSVの桁揃えや、NDJSONのフィールド投影に対応。
8,600万行を対象にした全文検索でも、大量のヒット結果を保持したまま一覧を軽快に辿れます。
「巨大ログを、コマンドを駆使せず人間の目で追う」。これが、本当に欲しかった体験でした。
開いたまま増え続けるログを、その場で書き換える
巨大ログを「見る」ための道具は世の中にいくつもあります。しかし、自分が欲しかったのは
その一歩先でした。
MrEditorの末尾追従(⌥⌘F)は、開いた後にファイルへ書き込まれた行を、リロードなしで
追従します。mmap の索引を、増えたバイトぶんだけ継ぎ足す設計だからです。
実際に検証しました。12MBの種ログを開いて末尾追従をONにし、外部プロセスから >> で
1行ずつ、計24行を追記していくと、ステータスバーの行数がリアルタイムに増え、画面が
自動で新しい行を流していきます。10GBでも全く同じ仕組みが動き、土台が mmap なので
追記のたびに全ロードが走るようなこともありません。
エディタで tail -f ができること自体は珍しくありません(例えば BBEdit の Tail Mode などは
非常に素直で優れた実装です)。ただ、私が探した限りでは、**「10GBを丸ごと開いたまま・
リロードせず増分で追いながら・その場で編集して保存できる」**ツールは見つかりませんでした。
追える道具(ビューア)は読み取り専用が多く、編集できる道具(エディタ)はファイルを
再読み込みする方式のため10GBの壁を越えられない。その「隙間」こそが、このエディタを作る
最大の動機になりました。
正直な限界(トレードオフ)
誠実でありたいので、現在の限界も隠さず書いておきます。
-
初期インデックス構築のタイムラグ
表示自体は一瞬(45〜80ms)ですが、全索引の構築には10GBのファイルで約10秒かかります。
バックグラウンドで処理されるためUIは固まりませんが、正確な総行数の表示と全文検索の
実行は、この構築完了を待つ必要があります。 -
アクティビティモニタ上のRSS(メモリ)表記
索引構築中、psコマンドで確認できる RSS が数GBまで上昇します。これは mmap による
ページキャッシュ(OS管理下の破棄可能なCleanメモリ)であり、メモリ圧迫時にはカーネルに
よって自動回収されます(実際、vmmapが報告する dirty は0バイトです)。しかし、
アクティビティモニタ上では大きな数字として見えてしまう点をご留意ください。
入手方法
-
ダウンロード(Apple署名・公証済み / macOS 13以降対応):
https://mr-tabata.github.io/MrEditor/ -
ソースコード(MITライセンス / Swift + AppKit / Universal Binary):
https://github.com/MR-TABATA/MrEditor
「Macに移行したけれど、秀丸エディタのような巨大ファイルへの強さを求めて彷徨っていた方」
「普段は less や tail -f で事足りているけれど、たまには巨大ログをGUIでじっくり
目で追いたい方」に向けて作りました。
ぜひ触ってみていただき、フィードバックをいただけると嬉しいです!