これは、なにをしたくて書いたもの?
Linuxで、メモリの断片化に関する情報が見れるようなので、少し調べてみました。
情報は、このあたりをベースにしています。
The /proc Filesystem — The Linux Kernel documentation
Ubuntu Manpage: proc - プロセスの情報を含む擬似ファイルシステム
ちなみに、今回は断片化の様子を確認したという話ではなく、あくまで情報の取得方法を見ているだけです。
環境
今回の確認環境は、こちら。Ubuntu Linux 20.04 LTSです。
$ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 20.04.3 LTS Release: 20.04 Codename: focal $ uname -srvmpio Linux 5.4.0-81-generic #91-Ubuntu SMP Thu Jul 15 19:09:17 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
4 CPU、メモリ8Gの構成です。
$ grep ^processor /proc/cpuinfo processor : 0 processor : 1 processor : 2 processor : 3 $ grep ^MemTotal /proc/meminfo MemTotal: 8054420 kB
/proc/buddyinfo、/proc/pagetypeinfo、/sys/kernel/debug/extfrag/unusable_index
メモリの断片化について確認するには、
/proc/buddyinfo
/proc/pagetypeinfo
/sys/kernel/debug/extfrag/unusable_index
あたりの情報を見ればよさそうです。
まずは、/proc/buddyinfo
から。
$ cat /proc/buddyinfo Node 0, zone DMA 1 0 0 1 2 1 1 0 1 1 3 Node 0, zone DMA32 3 3 1 1 1 0 2 3 2 3 745 Node 0, zone Normal 1831 712 379 292 304 35 10 7 2 19 1016
/proc/buddyinfo
では、メモリの断片化に関する情報を見ることができます。これは、OSやCPUがメモリを扱う単位である
ページを管理するために使う、バディアロケーターの統計情報です。
Documentation for /proc/sys/kernel/ / shmall
読み方ですが、各ゾーン(この例ではDMA、DMA32、Normal)で使用可能なチャンクの数が表示されています。
全部で11個あり、以下の計算式で算出できます。
(2 ^ order)* PAGE_SIZE
ここで、ページサイズは今回の環境では4KBでした。
$ getconf PAGE_SIZE 4096
つまり、4KB、8KB、16KB、32KB、64KB、128KB、256KB、512KB、1MB、2MB、4MBという並びになります。
たとえば、この例でDMAというゾーンであれば、4KBのチャンクが1つ、32KBのチャンクが1つ、64KBのチャンクが
1つ…4MBのチャンクが4つ、みたいな読み方になります。
Node 0, zone DMA 1 0 0 1 2 1 1 0 1 1 3
Normalというゾーンであれば、4KBのチャンクが1831、4MBのチャンクが1016あることになります。4MBのチャンクだけで、
4Gのメモリがあることになります。
Node 0, zone Normal 1831 712 379 292 304 35 10 7 2 19 1016
ここで、右にある大きなサイズのチャンクが小さくなっており、左にある小さなサイズのチャンクが多くなっている場合は
断片化が進んでいる(小さなチャンクしか残っていない)ことを示します。
どんなゾーンがあるかは、/proc/zoneinfo
で確認できます。
$ grep '^Node' /proc/zoneinfo Node 0, zone DMA Node 0, zone DMA32 Node 0, zone Normal Node 0, zone Movable Node 0, zone Device
Normalというのが、通常のゾーンでほとんどのメモリがここに収まります。
DMAは古くからある16MBのゾーンで、ドライバなどが使用します。
Is it time to remove ZONE_DMA? [LWN.net]
DMA32は、32ビット用に拡張されたDMAゾーンです。
Documentation for /proc/sys/vm/ — The Linux Kernel documentation
Normalゾーンは、こんな感じになっています。
Node 0, zone Normal pages free 1065288 min 10537 low 13171 high 15805 spanned 1286144 present 1286144 managed 1243715 protection: (0, 0, 0, 0, 0) nr_free_pages 1065288 nr_zone_inactive_anon 462 nr_zone_active_anon 12286 nr_zone_inactive_file 33396 nr_zone_active_file 89457 nr_zone_unevictable 4616 nr_zone_write_pending 0 nr_mlock 4616 nr_page_table_pages 365 nr_kernel_stack 2096 nr_bounce 0 nr_zspages 0 nr_free_cma 0 numa_hit 737828 numa_miss 0 numa_foreign 0 numa_interleave 62933 numa_local 737828 numa_other 0 pagesets cpu: 0 count: 319 high: 378 batch: 63 vm stats threshold: 42 cpu: 1 count: 200 high: 378 batch: 63 vm stats threshold: 42 cpu: 2 count: 53 high: 378 batch: 63 vm stats threshold: 42 cpu: 3 count: 288 high: 378 batch: 63 vm stats threshold: 42 node_unreclaimable: 0 start_pfn: 1048576
さらに詳細を/proc/pagetypeinfo
で見ることができます。
$ sudo cat /proc/pagetypeinfo Page block order: 9 Pages per block: 512 Free pages count per migrate type at order 0 1 2 3 4 5 6 7 8 9 10 Node 0, zone DMA, type Unmovable 1 0 0 1 2 1 1 0 1 0 0 Node 0, zone DMA, type Movable 0 0 0 0 0 0 0 0 0 1 3 Node 0, zone DMA, type Reclaimable 0 0 0 0 0 0 0 0 0 0 0 Node 0, zone DMA, type HighAtomic 0 0 0 0 0 0 0 0 0 0 0 Node 0, zone DMA, type CMA 0 0 0 0 0 0 0 0 0 0 0 Node 0, zone DMA, type Isolate 0 0 0 0 0 0 0 0 0 0 0 Node 0, zone DMA32, type Unmovable 1 0 0 0 0 0 1 1 1 1 0 Node 0, zone DMA32, type Movable 2 3 1 1 1 0 1 2 1 2 745 Node 0, zone DMA32, type Reclaimable 0 0 0 0 0 0 0 0 0 0 0 Node 0, zone DMA32, type HighAtomic 0 0 0 0 0 0 0 0 0 0 0 Node 0, zone DMA32, type CMA 0 0 0 0 0 0 0 0 0 0 0 Node 0, zone DMA32, type Isolate 0 0 0 0 0 0 0 0 0 0 0 Node 0, zone Normal, type Unmovable 168 152 70 2 9 4 0 1 0 16 15 Node 0, zone Normal, type Movable 1636 560 285 285 292 29 10 5 1 2 1001 Node 0, zone Normal, type Reclaimable 3 8 23 4 3 2 0 1 1 1 0 Node 0, zone Normal, type HighAtomic 0 0 0 0 0 0 0 0 0 0 0 Node 0, zone Normal, type CMA 0 0 0 0 0 0 0 0 0 0 0 Node 0, zone Normal, type Isolate 0 0 0 0 0 0 0 0 0 0 0 Number of blocks type Unmovable Movable Reclaimable HighAtomic CMA Isolate Node 0, zone DMA 1 7 0 0 0 0 Node 0, zone DMA32 2 1526 0 0 0 0 Node 0, zone Normal 106 2368 38 0 0 0
たとえば/proc/buddyinfo
ではDMA32ゾーンはこのような内容でしたが、
Node 0, zone DMA32 3 3 1 1 1 0 2 3 2 3 745
/proc/pagetypeinfo
ではその内訳を見ることができます。
Node 0, zone DMA32, type Unmovable 1 0 0 0 0 0 1 1 1 1 0 Node 0, zone DMA32, type Movable 2 3 1 1 1 0 1 2 1 2 745 Node 0, zone DMA32, type Reclaimable 0 0 0 0 0 0 0 0 0 0 0 Node 0, zone DMA32, type HighAtomic 0 0 0 0 0 0 0 0 0 0 0 Node 0, zone DMA32, type CMA 0 0 0 0 0 0 0 0 0 0 0 Node 0, zone DMA32, type Isolate 0 0 0 0 0 0 0 0 0 0 0
Movableなどをマイグレーションタイプと呼ぶようで、それぞれ以下のような意味になるようです。
- Unmovable … カーネルが内部的に使うもので、移行できないもの(長命)
- Movable … ユーザープロセス用のメモリで、移行可能なもの(短命)
- Reclaimable … ページキャッシュ、i-nodeキャッシュなど(短命)
- HighAtomic … These are high-order allocations belonging to callers that cannot sleep or perform any IO. In practice, this is restricted to jumbo frame allocation for network receive.(短命)
- CMA … 連続したメモリ割り当て領域
- Isolate … 使われない?
HighAtomicは意味がよくわかりませんでした…。
ここで移行と言っているのはメモリを使用しているプロセスが認識している仮想アドレスを変えず、ページの物理的な
位置を移動できることを指します。
Page migration — The Linux Kernel documentation
参考)
Group pages of related mobility together to reduce external fragmentation v28 [LWN.net]
Contiguous memory allocation for drivers [LWN.net]
A reworked contiguous memory allocator [LWN.net]
Linux memo 2020/10/17 - らるるの自宅と職場を往復する人生@それをすてるなんてとんでもない!
https://github.com/torvalds/linux/blob/v5.4/include/linux/mmzone.h#L41-L67
/proc/buddyinfo
でNormalゾーンを見ると、こんな感じになっています。
Node 0, zone Normal, type Unmovable 168 152 70 2 9 4 0 1 0 16 15 Node 0, zone Normal, type Movable 1636 560 285 285 292 29 10 5 1 2 1001 Node 0, zone Normal, type Reclaimable 3 8 23 4 3 2 0 1 1 1 0 Node 0, zone Normal, type HighAtomic 0 0 0 0 0 0 0 0 0 0 0 Node 0, zone Normal, type CMA 0 0 0 0 0 0 0 0 0 0 0 Node 0, zone Normal, type Isolate 0 0 0 0 0 0 0 0 0 0 0
あとは、/sys/kernel/debug/extfrag/unusable_index
。
$ sudo cat /sys/kernel/debug/extfrag/unusable_index Node 0, zone DMA 0.000 0.000 0.000 0.000 0.002 0.010 0.018 0.034 0.034 0.098 0.227 Node 0, zone DMA32 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.001 0.003 Node 0, zone Normal 0.000 0.001 0.003 0.004 0.006 0.011 0.012 0.012 0.013 0.014 0.023
こちらは、値が0.000に近づくほど利用可能なチャンクが多く、1.000に近づくほど利用可能なチャンクが少ないことを
表します。各ゾーンに対して11個の数字が並ぶのは、/proc/buddyinfo
と同じ読み方でOKです。
ちなみに、/proc/buddyinfo
などで見ていた値を合計すると、free
や/proc/meminfo
で見る"free"および"MemFree"の値と
ほぼ同じになります。
/proc/buddyinfo
の実行と、ほぼ同じタイミングで取得したfree -h
。
$ free -h total used free shared buff/cache available Mem: 7.7Gi 137Mi 7.0Gi 2.0Mi 561Mi 7.3Gi Swap: 1.9Gi 0B 1.9Gi
同じく、/proc/meminfo
。
$ cat /proc/meminfo MemTotal: 8054428 kB MemFree: 7338756 kB MemAvailable: 7645824 kB Buffers: 61396 kB Cached: 440440 kB SwapCached: 0 kB Active: 407000 kB Inactive: 135432 kB Active(anon): 49156 kB Inactive(anon): 1848 kB Active(file): 357844 kB Inactive(file): 133584 kB Unevictable: 18464 kB Mlocked: 18464 kB SwapTotal: 1999868 kB SwapFree: 1999868 kB Dirty: 160 kB Writeback: 0 kB AnonPages: 59060 kB Mapped: 48276 kB Shmem: 2212 kB KReclaimable: 73220 kB Slab: 125560 kB SReclaimable: 73220 kB SUnreclaim: 52340 kB KernelStack: 2096 kB PageTables: 1460 kB NFS_Unstable: 0 kB Bounce: 0 kB WritebackTmp: 0 kB CommitLimit: 6027080 kB Committed_AS: 271920 kB VmallocTotal: 34359738367 kB VmallocUsed: 10616 kB VmallocChunk: 0 kB Percpu: 2896 kB HardwareCorrupted: 0 kB AnonHugePages: 0 kB ShmemHugePages: 0 kB ShmemPmdMapped: 0 kB FileHugePages: 0 kB FilePmdMapped: 0 kB CmaTotal: 0 kB CmaFree: 0 kB HugePages_Total: 0 HugePages_Free: 0 HugePages_Rsvd: 0 HugePages_Surp: 0 Hugepagesize: 2048 kB Hugetlb: 0 kB DirectMap4k: 128876 kB DirectMap2M: 3966976 kB DirectMap1G: 4194304 kB
ここで、DMAゾーンの和(4KB x 1 + ... + 4MB x 3)とDMA32ゾーンの和(4kB x 3 + ... + 4MB x 745)と
Normalゾーンの和(4KB x 1831 + ... + 4MB x 1016)を合計すると、
$ cat /proc/buddyinfo Node 0, zone DMA 1 0 0 1 2 1 1 0 1 1 3 Node 0, zone DMA32 3 3 1 1 1 0 2 3 2 3 745 Node 0, zone Normal 1831 712 379 292 304 35 10 7 2 19 1016
こちらの値とほぼ等しくなります。
MemFree: 7338756 kB
vmstat
でも同じですね。
だいぶ走り書きな感じですが、とりあえず今回はこんなところで…。
参考
Linux メモリ断片化 (外部フラグメンテーション) の概要と解消方法 - Qiita