TL

メモリアロケータの内部(buddy systemとslab)

mallocが速い理由と断片化が起きる理由が、カーネルの内側から腑に落ちます。物理ページを配るbuddy、小物を配るslab、ユーザー空間のアリーナまで一気通貫で解剖します。

応用メモリアロケータbuddy systemslabmallocカーネル最終更新: 2026-06-21
TL;DR要点だけ先に
  • 1.カーネルの物理ページ割当はbuddy systemが担い、2のべき乗ブロックを分割・統合して外部断片化を抑える。
  • 2.ページより小さいオブジェクトはslab/slub/slobが担当し、型ごとのキャッシュで初期化コストと内部断片化を削る。
  • 3.ユーザー空間のmalloc(ptmalloc/tcmalloc/jemalloc)はアリーナとサイズ別ビンで、ロック競合を避けつつ高速に再利用する。

三層構えのアロケータ

メモリ割当は単層ではありません。カーネル内の物理ページ割当 と、その上に乗る 小オブジェクト割当、さらにユーザー空間の malloc が階層をなします。下の層ほど粒度が粗く、上の層ほど細かい要求を捌きます。各層が解く問題は共通で、確保・解放を高速にしつつ断片化を抑える ことです。

ユーザー空間: malloc/free  ← ptmalloc / tcmalloc / jemalloc(アリーナ + ビン)
   ↑ 足りなければ brk / mmap でページを要求
カーネル:    slab/slub/slob ← 小さなオブジェクト(数十〜数百バイト)
   ↑ ページ単位で要求
カーネル:    buddy system   ← 物理ページ(4KB の 2^n 倍)

buddy system:物理ページの分割と統合

Linux の物理ページ割当の中核が buddy system です。空きメモリを 2のべき乗ページ数のブロック(4KB×2^order、order=0〜10 が典型)で管理し、order ごとに空きブロックの フリーリスト を持ちます。

確保の流れはこうです。要求サイズ以上で最小の order を選び、その order に空きが無ければ 1つ上の order を半分に割る。割った片割れが buddy(相棒) で、もう片方をフリーリストに戻します。

order=2 (16KB) を要求、空きは order=4 (64KB) だけのとき:
[ 64KB ]            (order 4)
[32KB][32KB]        (order 4 → 3 に分割、片方を free list へ)
[16KB][16KB][32KB]  (order 3 → 2 に分割、片方を free list へ)
 └払出  └free  └free

解放時は逆で、自分の buddy も空いていれば即座に統合(coalesce) して上の order に戻します。buddy のアドレスは「ブロック先頭アドレス XOR ブロックサイズ」で O(1) に求まるのが巧妙な点です。

なぜ 2 のべき乗なのか

2のべき乗に固定するのは、buddy のアドレスをビット演算1発で算出でき、分割・統合を定数時間で行えるからです。任意サイズを許すと相棒探しが線形探索になり、統合判定が重くなります。代償として、要求が中途半端なサイズだとブロック内に未使用が残る 内部断片化 が生じます。

buddy は 外部断片化(空きの総量は足りるのに連続した大ブロックが取れない状態)を統合によって強力に抑えます。空き状況は /proc/buddyinfo で order 別に観察できます。物理ページと仮想アドレスの対応は 仮想記憶(ページング) を参照してください。

slab/slub/slob:オブジェクト単位の再利用

カーネルは task_structinode など 固定サイズの小さな構造体 を頻繁に作っては壊します。これをページ単位の buddy で扱うと、数百バイトのために 4KB を丸ごと使い、内部断片化が爆発します。そこで間に挟むのが slab アロケータ です。

仕組みの核は次の3点です。

  • キャッシュ単位:オブジェクトの型ごとに専用キャッシュ(kmem_cache)を作る。buddy から取った1〜数ページを slab とし、同型オブジェクトでびっしり敷き詰める。
  • 構築済みの再利用:解放されたオブジェクトは初期化済みの状態でリストに戻る。次の確保は コンストラクタを省いて即返せる
  • キャッシュ局所性:同型を連続配置するため CPU キャッシュに乗りやすい。
実装性質主な用途
slabメタデータ豊富・キュー多段で複雑歴史的な標準。デバッグ情報が手厚い
slubメタデータをページ構造体に寄せ簡素・スケーラブル現在の Linux の既定
slob極小・最小フットプリント組み込みなど省メモリ環境

現在の既定は slub です。slab のロック多用とメタデータ肥大を見直し、メタ情報を struct page 側へ寄せ、CPU ごとのアクティブ slab を持たせてロックなしの高速パスを作りました。slob は連結リスト1本で済ませる最小実装で、速度よりフットプリントを優先します。状況は /proc/slabinfo で確認できます。

型ごとのキャッシュが効く理由

汎用の可変長アロケータは「どのサイズにも対応」する代わりにサイズ管理のオーバーヘッドを持ちます。slab は「このキャッシュは全部この型・このサイズ」と決め打つことで、空きスロット管理を ビットマップやフリーリスト1本 に単純化し、確保・解放をほぼポインタ付け替えだけに落とせます。

ユーザー空間の malloc:アリーナとビン

malloc/free はカーネルではなく C ライブラリ側 の実装です。内部では brk や mmap で まとめてページを確保し、それを細かく切り分けて再利用します。毎回システムコールを呼ばないのが速さの源です(システムコールの境界は システムコール を参照)。

設計の二本柱が アリーナビン です。

  • アリーナ(arena):割当用メモリ領域の独立した塊。スレッドごと(または少数)に分けることで、ロック競合 を避けてマルチスレッドでスケールさせる。
  • ビン(bin):解放済みチャンクを サイズ別に並べたフリーリスト。同サイズの再利用要求に即応する。

主要3実装の戦略はこう違います。

実装並行性の鍵ビン/キャッシュ構造
ptmalloc2 (glibc)複数アリーナ + スレッド単位の tcachefast/small/large/unsorted bin、近年は tcache 前置
tcmalloc (Google)スレッドローカルキャッシュ中心サイズクラス別 free list + 中央ヒープ
jemalloc (FB/BSD)アリーナ多数 + per-CPU/スレッドの tcacheサイズクラス別 + 大領域は別管理、断片化に強い

glibc の ptmalloc では、小さな解放は tcache(スレッドローカルの単方向リスト)に入り、ロックも整合性チェックも最小で再利用されます。あふれた分が fastbin/smallbin などアリーナ共有のビンへ回ります。tcmalloc と jemalloc はこの「スレッドローカルで捌き、足りなければ中央へ」という二段構造をより徹底し、サイズクラス(要求を離散的な代表サイズに丸める)でビンを整理します。

サイズクラス丸めは内部断片化と表裏一体

40 バイト要求を 48 バイトのサイズクラスに丸めれば、管理は単純化し再利用も効きますが、8 バイトは必ず無駄になります。これが 内部断片化。クラスを細かくすれば無駄は減る一方、ビンの数とメタデータが増えます。アロケータ設計は常にこのトレードオフの上にあります。

試験・面接の要点

「buddy=物理ページ・外部断片化対策・統合は XOR で O(1)」「slab=型別キャッシュ・内部断片化と初期化コスト削減・既定は slub」「malloc=アリーナでロック競合回避・ビン/サイズクラスで再利用」の3点をセットで押さえると、層ごとの役割分担を問う設問に対応できます。

まとめ

  • buddy system は物理ページを2のべき乗ブロックで管理し、分割と O(1) 統合で外部断片化を抑える。
  • slab/slub/slob はページより小さい型固定オブジェクトを専用キャッシュで再利用し、内部断片化と初期化コストを削る。既定は slub。
  • ユーザー空間の malloc は brk/mmap で取ったページを アリーナサイズ別ビン で捌き、スレッドローカルキャッシュでロック競合を避ける。
  • 三層に共通する敵は 断片化ロック競合。各層が粒度に応じた戦略で同じ問題を解いている。

メモリ全体の地図は メモリ管理(スタックとヒープ)、ページとフレームの対応は ページングとスワップ と合わせて読むと、確保から物理メモリまでが一本につながります。

OS Article

メモリアロケータの内部(buddy systemとslab)を実務で読む

TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。

解決すること

メモリアロケータ

比較で見る軸

難易度: advanced / カテゴリ: OS / タグ数: 5

導入後に効く点

ページより小さいオブジェクトはslab/slub/slobが担当し、型ごとのキャッシュで初期化コストと内部断片化を削る。

先に潰すリスク

用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。

数字・仕様の読み方
難易度
advanced
カテゴリ
OS
タグ数
5

判断チェックリスト

  • 自社の用途が「メモリアロケータ / buddy system」に近いか確認する。
  • 強みである「カーネルの物理ページ割当はbuddy systemが担い、2のべき乗ブロックを分割・統合して外部断片化を抑える。」が本当に評価軸になるか確認する。
  • 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
  • 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
  • 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
  • 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。

次に確認する観点

メモリアロケータbuddy systemslabmallocカーネルメモリアロケータbuddy systemslab
参考: 公式情報