过度使用记账(Overcommit Accounting)¶
overcommit handing modes¶
Linux内核支持以下 overcommit
处理模式:
0
: 启发式overcommit
启发式过度分配
拒绝明显的地址空间过度使用,用于典型系统(默认配置)。这种处理模式可以确保严重的疯狂分配(seriously wild allocation)失败,同时允许(适当) overcommit
以减少swap空间使用。这个模式也允许 root
用户分配更多的内存。
1
: 始终overcommit
始终过度分配
适合一些科学应用。典型的案例是使用稀疏矩阵(sparse arrays)的代码,并且仅依赖完全由 零页面
(zero pages)组成的虚拟内存
2
: 禁止overcommit
禁止过度分配
设置下,系统的总地址空间提交(total address space commit)不允许超过 swap + (物理内存*overcommit_ratio)
的可配置数量( overcommit_ratio
默认是 50%
)。根据内存使用量,大多数情况下进程在访问页面时不会被终止,但是会在恰当的时候收到内存分配错误
检查和设置 overcommit
处理模式¶
sysctl
检查 vm.overcommit_memory
设置值:
sysctl vm.overcommit_memory
通常情况下,该值是 0
(启发式过度分配):
vm.overcommit_memory = 0
直接检查 /proc/sys
下的配置也可以查看该配置:
cat /proc/sys/vm/overcommit_memory
配合 overcommit
配置值 2
的两个参数¶
当 vm.overcommit_memory
设置为 2
(也就是禁止过度分配)时,此时有两个配套参数(仅在 vm.overcommit_memory = 2
时生效):
vm.overcommit_ratio
过度分配百分比,也就是swap + RAM
的百分比允许过度分配vm.overcommit_kbytes
过度分配绝对值
上述两个配套参数入口也位于 /proc/sys/vm
下:
# ls /proc/sys/vm/overcommit*
/proc/sys/vm/overcommit_kbytes /proc/sys/vm/overcommit_memory /proc/sys/vm/overcommit_ratio
这两个值默认不生效( 因为系统默认 vm.overcommit_memory = 0
):
# sysctl vm.overcommit_kbytes
vm.overcommit_kbytes = 0
# sysctl vm.overcommit_ratio
vm.overcommit_ratio = 50
当前 overcomit
¶
当前系统的过度使用限制(overcommit limit)和提交量(ammount commmited)可以通过 /proc/meminfo
的 CommitLimit
和 Committed_AS
查看
案例:
检查Linux系统内存分配:
cat /proc/meminfo
输出信息:
MemTotal: 197928076 kB
MemFree: 144126316 kB
MemAvailable: 144382540 kB
Buffers: 247316 kB
Cached: 1113060 kB
SwapCached: 0 kB
Active: 15591136 kB
Inactive: 36330216 kB
Active(anon): 14844596 kB
Inactive(anon): 35731580 kB
Active(file): 746540 kB
Inactive(file): 598636 kB
Unevictable: 31172 kB
Mlocked: 28100 kB
SwapTotal: 0 kB
SwapFree: 0 kB
Dirty: 276 kB
Writeback: 0 kB
AnonPages: 50592164 kB
Mapped: 192984 kB
Shmem: 6128 kB
KReclaimable: 157340 kB
Slab: 1106652 kB
SReclaimable: 157340 kB
SUnreclaim: 949312 kB
KernelStack: 12784 kB
PageTables: 105972 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 98964036 kB
Committed_AS: 52750596 kB
VmallocTotal: 34359738367 kB
VmallocUsed: 310252 kB
VmallocChunk: 0 kB
Percpu: 48384 kB
HardwareCorrupted: 0 kB
AnonHugePages: 50331648 kB
ShmemHugePages: 0 kB
ShmemPmdMapped: 0 kB
FileHugePages: 0 kB
FilePmdMapped: 0 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
Hugetlb: 0 kB
DirectMap4k: 578044 kB
DirectMap2M: 10823680 kB
DirectMap1G: 191889408 kB
可以看到 MemTotal
表示主机实际安装内存大小(192G); 内存过度使用当前限制大约是 94.4GB ,而当前过度分配提交量是 50.3GB
验证¶
# cat /proc/meminfo | grep 'MemTotal\|SwapTotal'
MemTotal: 197928076 kB
SwapTotal: 0 kB
# cat /proc/sys/vm/overcommit_memory
0
调整为禁止overcommit策略
# echo 2 > /proc/sys/vm/overcommit_memory
# sysctl vm.overcommit_memory
vm.overcommit_memory = 2
此时 overcommit_ratio 参数生效: 50%
# sysctl vm.overcommit_ratio
vm.overcommit_ratio = 50
# cat /proc/meminfo | grep 'CommmitLimit\|Committed_AS'
Committed_AS: 52758336 kB
# cat /proc/meminfo | grep 'CommitLimit\|Committed_AS'
CommitLimit: 98964036 kB
Committed_AS: 52758336 kB
调整 overcommit_ratio 参数到 200%,可以看到 CommitLimit 一下子从 98964036 kB 改变到 395856152 kB
# sysctl vm.overcommit_ratio=200
vm.overcommit_ratio = 200
# sysctl vm.overcommit_ratio
vm.overcommit_ratio = 200
# cat /proc/meminfo | grep 'CommitLimit\|Committed_AS'
CommitLimit: 395856152 kB
Committed_AS: 52758336 kB
恢复默认的 "启发型overcommit模式"
# echo 0 > /proc/sys/vm/overcommit_memory
# cat /proc/meminfo | grep 'CommitLimit\|Committed_AS'
CommitLimit: 395856152 kB
Committed_AS: 52758336 kB
在启发式overcommit模式,之前在禁止overcommit模式下配置的 overcommit_ratio 还是200,此时不会自动收缩 CommitLimit
# sysctl vm.overcommit_ratio=50
vm.overcommit_ratio = 50
# cat /proc/meminfo | grep 'CommitLimit\|Committed_AS'
CommitLimit: 98964036 kB
Committed_AS: 52758336 kB