違いました。Chrome は 1 つのタブ = 1 つの独立したプロセス として扱っています。
OS から見ると、Chrome は 1 個のアプリじゃなくて、たくさんの小さいプロセスの集合。タブ 30 個なら、30 個以上のプロセスが同時に動いているイメージ。
これは マルチプロセス・アーキテクチャ という設計で、2008 年の Chrome 初代から採用されているもの。安定性とセキュリティのためにこうなっているらしいです。
[ 一般的なアプリ ] ┌────────────────┐ │ 1 プロセス │ │ すべての機能 │ └────────────────┘ [ Chrome ] ┌──────────────────────────┐ │ Browser Process (本体) │ │ ┌────────┐ ┌────────┐ │ │ │Renderer│ │Renderer│… │ │ │Tab A │ │Tab B │ │ │ └────────┘ └────────┘ │ │ ┌────────┐ ┌────────┐ │ │ │GPU │ │Network │ │ │ └────────┘ └────────┘ │ └──────────────────────────┘
+ ボタンを押すと、Chrome 本体 (Browser Process) が OS に「新しいプロセスを作って」と依頼します。
OS は新しいプロセスにメモリ空間を割り当てて、その中で Renderer Process と呼ばれる "タブ用のプロセス" が起動。中には V8(JS エンジン)と Blink(HTML/CSS レンダリングエンジン)が入ってる。
空のタブでも、起動した瞬間に 30〜50 MB くらいメモリを使うらしいです。「中身ゼロ」じゃないんですね。
[ + ボタン押下 ]
↓
Browser Process が OS にお願い
↓
OS: 新しいメモリ空間を確保
↓
新しい Renderer Process 起動
┌──────────────┐
│ ┌──────────┐ │
│ │ V8 │ │ JS エンジン
│ ├──────────┤ │
│ │ Blink │ │ レンダリング
│ ├──────────┤ │
│ │ DOM tree │ │ 空っぽ
│ └──────────┘ │
└──────────────┘
~30-50 MB
URL からページが表示されるまで、おおまかに 4 ステップ。
この間ずっと、Renderer Process はメモリにデータを溜め込みながら動いてます。Gmail のような重いサイトだと、ここで 300〜500 MB まで膨らむことも。
URL: https://example.com
↓
[ 1. DNS ] example.com = 203.0.113.5
↓
[ 2. HTTP ] GET / → HTML 取得
↓
[ 3. Parse ] HTML 解析
↓ <link> <script> <img> を発見
追加ダウンロード並列実行
↓
[ 4. Render ]
DOM ツリー組み立て
↓
レイアウト計算
↓
ピクセルに描画
これが Site Isolation。Chrome 67 (2018年) からデフォルトで有効になった機能で、1 タブの中でも、サイトが違えばプロセスを分ける ようになりました。
例えば news.example.com を開くと、そのページに埋め込まれた YouTube 動画、Twitter ウィジェット、広告、解析タグ…がそれぞれ別プロセスに。1 タブで 5〜6 プロセス、ということも。
理由は Spectre 脆弱性。同じプロセスにいると、悪意あるサイトが他サイトのメモリを覗ける可能性があったので、物理的に分けることで防御している。
タブ: news.example.com ┌──────────────────────────┐ │ Renderer A: example.com │ メイン │ ┌────────────────────┐ │ │ │ <iframe ads.com> │ │ │ └────────────────────┘ │ │ ┌────────────────────┐ │ │ │ <iframe yt.com> │ │ │ └────────────────────┘ │ └──────────────────────────┘ ↓ 実際の OS プロセス [PID 100] example.com [PID 101] ads.com (iframe) [PID 102] youtube.com (iframe) [PID 103] analytics.com → メモリ +10〜15%
そうみたいです。Discarded された後にクリックすると、タブはまだそこにあるけど、中身は最初からリロードされる。
Chrome 設定の Memory Saver モードがこれを積極的にやってくれる機能。一定時間使ってないタブを Discarded にして、メモリを返す。
freeze/resume イベントを使って、自分のサイトが凍結される前に状態を保存できる。× を押すと、Browser Process が OS にそのプロセスを kill するよう依頼。OS は、そのプロセスが使ってたメモリ空間を回収します。
これは 即座に・確実に 起きるみたいです。タブ閉じれば、そのタブ分のメモリは戻ってくる。30 タブ閉じれば 2〜4 GB 返ってきても不思議じゃない。
ただし、同じプロセスを共有してる他タブが残ってると、メモリ完全には返らないことも。Site Isolation のせいで、思ったほど解放されないケースもあるとか。
[ × ボタン押下 ]
↓
Browser Process が OS に依頼:
"kill PID 100"
↓
OS の動き:
1. プロセスを停止
2. メモリ空間を解放
3. ファイルハンドル等を回収
↓
~ 数ms で完了
残ったもの:
・ブラウザの履歴
・Cookie / localStorage
・bfcache (もし対象なら)