手当たり次第に書くんだ

飽きっぽいのは本能

VM の HugePages / TLB / NUMA 設計 – page size と memory placement を確認する

VM の memory 性能は、割り当て容量だけでは決まりません。page size、TLB miss、vCPU と memory の NUMA placement、page reclaim、ballooning、KSM によって、同じ容量でも throughput と tail latency が変わります。

この記事では、事前予約する HugeTLB と kernel が自動管理する Transparent HugePages を分け、2 MiB / 1 GiB page の選択、NUMA node ごとの予約、libvirt XML、capacity、起動と migration の検証方法を確認します。

HugeTLB、THP、通常 page を分ける

方式allocation運用上の特徴
通常 page通常の memory allocator が管理する柔軟だが、大きな working set では page 数が増える
HugeTLB専用 pool へ明示的に予約する決定性を得やすいが、他用途へ使えず swap もできない
Transparent HugePageskernel が page を自動的に昇格・分割する予約 pool は不要だが、allocation と compaction の挙動を考慮する

HugeTLB と THP は、どちらも大きな page を使う仕組みですが同じものではありません。libvirt の memoryBacking で HugePages を指定する設計と、host の THP policy を有効にする設計を混同しないことが重要です。

page size と TLB の関係を確認する

TLB は、virtual address から physical address への変換結果を保持する cache です。同じ memory 容量なら、page size が大きいほど必要な page 数が減り、限られた TLB entry で広い範囲を扱えます。

page size64 GiB を構成する page 数判断
4 KiB16,777,216通常 page。柔軟性が高い
2 MiB32,768HugeTLB で扱いやすく、細かい capacity 調整が可能
1 GiB64page 数は少ないが、予約単位と fragmentation の影響が大きい

page 数が減ることは TLB miss 削減の可能性を示しますが、必ず workload が速くなるとは限りません。working set、memory access pattern、CPU architecture、nested page table、NUMA remote access を含め、適用前後で測定します。

host が対応する page size と pool を確認する

最初に host が対応する HugeTLB page size、予約総数、空き数、使用数、THP policy を読み取ります。/proc/meminfoHugePages_* は default size の pool を中心に示すため、複数 size を使う場合は sysfs も確認します。

grep -E 'Huge|AnonHuge' /proc/meminfo
ls -1 /sys/kernel/mm/hugepages
cat /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
cat /sys/kernel/mm/hugepages/hugepages-2048kB/free_hugepages
cat /sys/kernel/mm/hugepages/hugepages-1048576kB/nr_hugepages
cat /sys/kernel/mm/transparent_hugepage/enabled
cat /sys/kernel/mm/transparent_hugepage/defrag

sysfs に対象 directory がなければ、その page size を同じ方法では利用できません。1 GiB page を前提にする前に、CPU、kernel、boot parameter、pool の実在を確認します。

NUMA node ごとの HugePages を確認する

NUMA host では、HugeTLB pool の総数だけでなく node ごとの配置が重要です。VM の vCPU が node 0 で動いても、必要な HugePages が node 1 にしかなければ、起動失敗または意図しない memory placement につながります。

lscpu -e=CPU,NODE,SOCKET,CORE,ONLINE
numactl --hardware
numastat -c
cat /sys/devices/system/node/node*/meminfo
cat /sys/devices/system/node/node*/hugepages/hugepages-2048kB/nr_hugepages
cat /sys/devices/system/node/node*/hugepages/hugepages-2048kB/free_hugepages
  • vCPU を置く CPU と NUMA node
  • VM memory を割り当てる node
  • node ごとの HugePages 総数と空き数
  • NIC、NVMe、HBA が接続された NUMA node
  • host OS、QEMU、page cache に残す通常 memory
  • 障害時に VM が移動する先の pool

runtime で HugeTLB pool を増やす場合、必要な連続 memory を確保できず、要求数に届かないことがあります。kernel boot の早い段階は memory fragmentation が少ないため、大きな固定 pool は boot parameter で確保する方が再現しやすい場合があります。

VM の memoryBacking と numatune を確認する

libvirt では memoryBackinghugepages で page size を指定し、numatune で host NUMA node の policy を指定できます。次は guest NUMA node 0 に 2 MiB page を使い、host node 0 へ memory を限定する例です。

<memoryBacking>
  <hugepages>
    <page size='2' unit='M' nodeset='0'/>
  </hugepages>
  <nosharepages/>
</memoryBacking>
<numatune>
  <memory mode='strict' nodeset='0'/>
</numatune>

nodeset の意味は要素ごとに確認します。memoryBacking の page 指定では guest NUMA node との対応を表し、numatune では host NUMA node の memory policy を表します。guest NUMA topology を定義していない VM に複雑な size 分割を入れる前に、XML 全体を確認します。

nosharepages は、その domain で memory merge、つまり KSM を無効にする指定です。locked は別の制約であり、必要性と host 側の lock limit を確認せずに追加しません。

実行中と永続 XML を分けて確認する

実行中の VM と次回起動時の XML が一致しているとは限りません。HugePages の適用確認では、live XML、inactive XML、NUMA policy、balloon、QEMU process の memory map を対応付けます。

virsh dumpxml vm01
virsh dumpxml vm01 --inactive
virsh numatune vm01
virsh dommemstat vm01
virsh domstats vm01 --balloon --memory
virsh vcpupin vm01
virsh emulatorpin vm01

XML に hugepages があっても、意図した size と node で実 memory が確保されたかは別に確認します。起動 log、QEMU process の smaps、node ごとの free HugePages の差分を合わせて見ます。

必要 page 数と host capacity を計算する

必要 page 数は、HugePages へ載せる memory 容量を page size で割って求めます。64 GiB を 2 MiB page で構成するなら 32,768 pages、1 GiB page なら 64 pages です。ただし、VM の設定 memory と host の予約総量を機械的に同じにするだけでは不十分です。

capacity 項目確認すること
VM memoryguest が使う memory と memory slot の構成
QEMU overheadpage table、device、process 自体に必要な通常 memory
host reservekernel、service、page cache、monitoring の余力
NUMA balanceVM ごとの必要 pages が対象 node にあるか
failover障害時に移動先 host で同じ pool を確保できるか
growthmemory hotplug、VM 増設、maintenance 時の余力

HugeTLB pages は pool に予約されると通常用途には使えず、memory pressure が高くても swap できません。予約しすぎると host の通常 memory を圧迫し、少なすぎると VM を起動できません。

Transparent HugePages の policy と実使用量を見る

THP は予約 pool ではなく、kernel が anonymous memory などを大きな page へ昇格または分割する仕組みです。alwaysmadvisenever の policy だけでなく、defrag policy、khugepaged、実際の AnonHugePages を確認します。

観点確認すること
enabledsystem-wide policy と size ごとの policy
defragpage fault 時の reclaim / compaction による latency
khugepagedbackground collapse の進行と CPU 使用
実使用量/proc/meminfo と process の smaps
変更反映既存 mapping では application restart が必要か

THP を一律に無効または有効にするのではなく、workload と kernel の挙動を測定します。明示的 HugeTLB を利用する VM があっても、host 上の他 process に対する THP policy は別に評価します。

ballooning と KSM の境界を決める

機能得られるもの専有に近い VM での注意
ballooningguest から memory を回収できる実 memory の保証と page pool の前提が曖昧になる
KSM同一内容の page を merge できるscan と copy-on-write の負荷、分離境界を確認する
HugeTLB明示した page pool を利用できる共有や回収より reservation を優先する設計になる
nosharepagesdomain の memory merge を無効にするhost 全体の KSM policy とは別に管理する

best effort VM の集約率を優先する設計と、NFV、DPDK、database、低遅延 VM の memory 決定性を優先する設計を同じ policy にしないことが重要です。VM class ごとに ballooning、KSM、HugeTLB の扱いを決めます。

起動、再起動、migration を検証する

試験合格条件
cold start対象 node に必要 pages があり、VM が意図した size で起動する
restart使用後に pages が pool へ戻り、再起動結果を再現できる
concurrent start複数 VM の起動順序が変わっても必要 pool を確保できる
memory pressurehost の通常 memory と service に必要な headroom が残る
migration移行先の CPU、NUMA、page size、pool、libvirt XML が互換である
failover片系障害後の収容数でも必要 pages と通常 memory が足りる

HugePages の性能試験だけでなく、起動可能性と運用可能性を試します。migration できない構成を採用する場合は、それを障害復旧と maintenance の制約として明示します。

適用前後を同じ条件で比較する

  • 同じ vCPU、memory、NUMA topology、workload を使う
  • throughput と p95 / p99 latency を同時に測る
  • TLB miss、page fault、NUMA remote access を比較する
  • THP collapse、split、compaction の変化を確認する
  • host の free HugePages と通常 memory の余力を記録する
  • 改善しない場合に元の XML と pool へ戻せるようにする

page size だけでなく NUMA placement も同時に変えると、どちらが効いたのか分かりません。可能な範囲で変更を分け、同じ負荷区間で counter の差分を比較します。

よくある失敗

失敗問題確認すること
HugeTLB と THP を同じものとして扱う予約と自動昇格の挙動を混同するpool、sysfs policy、XML
host 全体の総数だけを見る必要 node に pages がないnode ごとの total / free
VM memory 分だけ予約するhost の通常 memory が不足するQEMU overhead と host reserve
1 GiB page を常に選ぶ予約単位が大きく capacity が硬直するworking set と実測効果
XML があれば適用済みと考えるsize と node が意図どおりでないsmaps、pool 差分、起動 log
性能試験だけ行う再起動と failover で起動できない運用 lifecycle 全体

まとめ

VM の HugePages 設計では、通常 page、HugeTLB、THP を分け、page size、TLB、NUMA placement、ballooning、KSM を同じ memory policy として確認します。大きな page は TLB 効率を改善する可能性がありますが、予約量と配置が新しい制約になります。

host が対応する size、node ごとの pool、live / inactive XML、実 memory map を記録し、必要 pages と host reserve を計算します。その後、性能、起動、再起動、migration、failover を同じ設計条件で検証することが、HugePages を安全に採用するための要点です。

関連する記事
VM の HugePages / TLB / NUMA 設計 – page size と memory placement を確認する

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)

トップへ戻る