🧠【初心者向け】CPUキャッシュ・NUMA・TLB をやさしく解説(図解あり)
プログラムの性能は
CPU・メモリ・キャッシュ の関係で大きく変わります。
しかし、この「低レイヤーの仕組み」は普段触れる機会が少なく、
初心者にとってはブラックボックスになりがちです。
- CPUキャッシュって何?
- L1 / L2 / L3 の違いって?
- NUMA構成のサーバーで何が起きる?
- メモリアクセスが遅いのはなぜ?
- TLBってなんの略?
- Javaプログラムにどう影響するの?
この記事では
初心者向けのイメージ → 深掘りの内部構造 の順で
CPUまわりの基礎を“本質から”理解できるようまとめます。
✨ 結論
✔ メモリアクセスの速度は「CPUキャッシュ」が支える
✔ L1 → L2 → L3 → メモリ の順に遅くなる
✔ NUMA構成では“メモリの遠近”が性能を変える
✔ TLBは「アドレス変換キャッシュ」であり、外すと激遅
✔ 高速化の本質は「近い場所のデータをまとめて使う」
CPUキャッシュの本質(まずはここから)
CPU は メモリより圧倒的に速い ため、
メモリを直接読み書きすると遅くなります。
そこで使われる仕組みが CPUキャッシュ。
🔹 図解(短線版)
CPU
├ L1キャッシュ(超高速・超小容量)
├ L2キャッシュ(高速)
└ L3キャッシュ(大容量・遅め)
↓
メインメモリ(遅い)
アクセス速度の違い(直感的に理解)
速度イメージ(極簡易化)
L1 → 1〜4 サイクル
L2 → 4〜12 サイクル
L3 → 30〜40 サイクル
メモリ → 200〜300 サイクル
メモリは L1 の50〜100倍遅い。
キャッシュヒット/ミスとは?
- ヒット:必要なデータがキャッシュにある(高速)
- ミス:キャッシュにない(メモリ参照で激遅)
頻繁に触るデータはキャッシュに載りやすい。
データの「局所性」がなぜ重要か?
CPU の最適化は
データ局所性(Locality) が本質。
✔ 時間的局所性
同じデータを何度も使う
✔ 空間的局所性
近くのデータが連続して使われる
🔹 図解(空間的局所性)
[100][101][102][103]
↑ ↑ ↑ 近くを連続でアクセス
NUMA(メモリの遠近による違い)
サーバーでは
CPUが複数のメモリバンクを持つ NUMA構成 が一般的。
🔹 図解(短線版)
Node0: CPU + メモリ
Node1: CPU + メモリ
Node0 のCPUが Node1のメモリ にアクセスすると遅くなる。
TLB(Translation Lookaside Buffer)とは?
TLBは
仮想アドレス → 物理アドレスの変換を高速化するキャッシュ。
仮想メモリを使うOSでは
アドレス変換が頻発するため、
TLBがないと毎回ページテーブルをたどって遅くなる。
✔ TLBミスは地味に重い
TLBミス → ページテーブル参照 → メモリアクセス
→ キャッシュミスよりさらに複雑で遅い
Javaプログラムへの影響(初心者でも理解できる範囲)
✔ 大きな配列をランダムアクセスすると遅い
→ 空間的局所性が失われる
✔ 連続データ構造(配列)は高速
→ キャッシュヒットしやすい
✔ オブジェクトが飛び飛びに配置されると遅い
→ Javaのヒープ構造による“参照追跡コスト”
✔ parallelStream が遅い原因の一部は NUMA
→ コアが違うメモリバンクを参照すると遅い
ここまでのまとめ(初心者向け)
- CPU → キャッシュ → メモリ の順に遅くなる
- L1/L2/L3 は“近いほど速い”
- NUMA では“どのCPUのメモリか”で速度が変わる
- アドレス変換は TLB が高速化している
- 高速化の本質は「近くのデータをまとめて使う」
▼▼ 深掘り編ここから ▼▼
キャッシュライン(Cache Line)の本質
CPUは 1バイトずつ ではなく
キャッシュライン(通常64バイト) 単位で読み込む。
🔹 図解
メモリ:
[0][1][2]...[63] → 1キャッシュライン
1個の変数を読む → 近くの63バイトも勝手に載る
✔ ゲームや高速処理では
“構造体をキャッシュライン境界に揃える” のが常識。
False Sharing(偽共有)
複数スレッドが
異なる変数なのに同じキャッシュラインに載っている
と、キャッシュが無駄に同期されて遅くなる。
🔹 図解
ThreadA → varA(ライン1)
ThreadB → varB(同じライン1)
→ 書き込みのたびにライン全体が同期…激遅!
→ 高性能アプリケーションで深刻な問題。
TLBと巨大ページ(Huge Page)
TLBはページ単位(4KB)でキャッシュするため
多くのメモリを扱う場合、TLBミスが増えやすい。
HugePage(2MB / 1GB)を使うと
TLBの負荷が激減する。
NUMA最適化の具体例
- スレッドとメモリを同じノードに固定する
- メモリを分散せずローカル化する
- 並列処理でノードを跨がないように設計する
大規模サービスでは常識のチューニング。
Deep Friendly Tech の一言(後書き)
CPUキャッシュ・NUMA・TLB は
アプリの速度がなぜ変わるか を理解するための
“究極の低レイヤー知識” です。
この領域を知っているだけで
- パフォーマンス問題の原因が読める
- 並列処理・高速化の本質が掴める
- Java の内部構造の理解が一段深くなる
エンジニアとしてのレベルが
確実に一段上がります。

コメント