![似乎没有什么可以解释 Linux 下缺少的 5GB 内存](https://linux22.com/image/1508775/%E4%BC%BC%E4%B9%8E%E6%B2%A1%E6%9C%89%E4%BB%80%E4%B9%88%E5%8F%AF%E4%BB%A5%E8%A7%A3%E9%87%8A%20Linux%20%E4%B8%8B%E7%BC%BA%E5%B0%91%E7%9A%84%205GB%20%E5%86%85%E5%AD%98.png)
我有 Kubuntu 16.04,并使用 ZFS 作为大数据分区(RAIDZ1)
我丢失了 5GB 的 RAM,不知道它去哪儿了。而且这不是缓存
根据我能想到的所有工具,我目前有以下统计数据:
Actively used: 9458.3 MB
Inacively used: 2544.5 MB
Mapped for IO: 2433.0 MB
Buffers: 242.6 MB
Slab: 6669.2 MB
Page Tables: 91.0 MB
Cached: 3758.1 MB
Dirty: 0.1 MB
Writeback: 0.0 MB
Free: 1856.5 MB
------------------------------
Total: 27053.3 MB
Total Memory: 32133.5 MB
------------------------------
Missing ???: 5080.2 MB
所以 5 GB 的 RAM 未被占用。它们去哪儿了?
工具输出
nmon:
RAM High Low Swap Page Size=4 KB │
│ Total MB 32133.5 -0.0 -0.0 8195.5 │
│ Free MB 1856.5 -0.0 -0.0 8195.5 │
│ Free Percent 5.8% 100.0% 100.0% 100.0% │
│ MB MB MB │
│ Cached= 3758.1 Active= 9458.3 │
│ Buffers= 242.6 Swapcached= 0.0 Inactive = 2544.5 │
│ Dirty = 0.1 Writeback = 0.0 Mapped = 2433.0 │
│ Slab = 6669.2 Commit_AS = 16647.1 PageTables= 91.3 │
│ Large (Huge) Page Stats ───────────────────────────────────────────────────────────────────────────────────────────────│
│ There are no Huge Pages │
│ - see /proc/meminfo │
│ │
│ Virtual-Memory ────────────────────────────────────────────────────────────────────────────────────────────────────────│
│nr_dirty = 37 pgpgin = 0 High Normal DMA │
│nr_writeback= 0 pgpgout = 0 alloc 0 343 0 │
│nr_unstable = 0 pgpswpin = 0 refill 0 0 0 │
│nr_table_pgs= 23384 pgpswpout = 0 steal 0 0 0 │
│nr_mapped = 622856 pgfree = 305 scan_kswapd 0 0 0 │
│nr_slab = -1 pgactivate = 0 scan_direct 0 0 0 │
│ pgdeactivate= 0 │
│allocstall = 0 pgfault = 74 kswapd_steal = 0 │
│pageoutrun = 0 pgmajfault = 0 kswapd_inodesteal= 0 │
│slabs_scanned= 0 pgrotated = 0 pginodesteal = 0
猫/ proc / memstat
MemTotal: 32904740 kB
MemFree: 1759548 kB
MemAvailable: 5372548 kB
Buffers: 249072 kB
Cached: 3852616 kB
SwapCached: 0 kB
Active: 9819328 kB
Inactive: 2609860 kB
Active(anon): 8334856 kB
Inactive(anon): 412176 kB
Active(file): 1484472 kB
Inactive(file): 2197684 kB
Unevictable: 7932 kB
Mlocked: 7932 kB
SwapTotal: 8392188 kB
SwapFree: 8392188 kB
Dirty: 224 kB
Writeback: 0 kB
AnonPages: 8335424 kB
Mapped: 2497092 kB
Shmem: 416004 kB
Slab: 6829716 kB
SReclaimable: 333652 kB
SUnreclaim: 6496064 kB
KernelStack: 26496 kB
PageTables: 95636 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 24844556 kB
Committed_AS: 17097748 kB
VmallocTotal: 34359738367 kB
VmallocUsed: 0 kB
VmallocChunk: 0 kB
HardwareCorrupted: 0 kB
AnonHugePages: 4306944 kB
CmaTotal: 0 kB
CmaFree: 0 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
DirectMap4k: 9029708 kB
DirectMap2M: 22384640 kB
DirectMap1G: 2097152 kB
免费-h
total used free shared buff/cache available
Mem: 31G 19G 1.8G 406M 10G 5.2G
Swap: 8.0G 0B 8.0G
在顶上
MEM | tot 31.4G | free 1.8G | | cache 3.7G | dirty 0.1M | buff 243.5M | | slab 6.5G | | | | | |
SWP | tot 8.0G | free 8.0G | | | | | | | | | | vmcom 16.3G | vmlim 23.7G |
附加信息/故事
我只有 16GB 内存,发现系统开始轻微交换。但不是一直交换。似乎内存使用量一直在增长,直到开始使用几兆字节的交换,然后停止增长。这是我第一次了解“slab”,发现我的很多内存都因为 ZFS 而转移到了那里。
太好了,没问题,所以我又安装了 16GB 内存,这应该可以了,对吧?但我又看到了同样的情况。内存不断增长,直到它开始稍微使用交换。但这次我找不到 5GB 的去向。在 Windows 下,我习惯使用正确的工具来查找每页内存的用途(https://www.youtube.com/watch?v=AjTl53I_qzY),但我有点迷茫了。5Gb 就这样没了。这是内核内存泄漏吗?
现在我设定swappiness 设置为 15,这似乎“暂时”阻止使用交换,但 5 GB 仍然消失了。
更新 1: 现在已运行两周了,这种影响几乎消失了。
│ Memory Stats ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── │
│ RAM High Low Swap Page Size=4 KB │
│ Total MB 32133.5 -0.0 -0.0 8195.5 │
│ Free MB 1871.9 -0.0 -0.0 8186.4 │
│ Free Percent 5.8% 100.0% 100.0% 99.9% │
│ MB MB MB │
│ Cached= 6275.9 Active= 10217.1 │
│ Buffers= 363.4 Swapcached= 1.3 Inactive = 3134.5 │
│ Dirty = 0.2 Writeback = 0.0 Mapped = 3911.0 │
│ Slab = 6159.5 Commit_AS = 13696.9 PageTables= 95.0
Actively used: 10217.1 MB
Inacively used: 3134.5 MB
Mapped for IO: 3911.0 MB
Buffers: 363.4 MB
Slab: 6159.5 MB
Page Tables: 95.0 MB
Cached: 6275.9 MB
Dirty: 0.2 MB
Writeback: 0.0 MB
Free: 1871.9 MB
------------------------------
Total: 32028,3 MB
Total Memory: 32133.5 MB
------------------------------
Missing ???: 105.2 MB
真正未使用的(空闲)内存保持相当稳定。但缓存和映射却增加了。这似乎确实有一些隐藏的缓存正在慢慢耗尽,但未显示在统计数据中。
Silvio Massina 提到它可能是 ARC。以下是
cat /proc/spl/kstat/zfs/arcstats
6 1 0x01 91 4368 56409879056 315868863969705
name type data
hits 4 15276585
misses 4 1100779
demand_data_hits 4 10451405
demand_data_misses 4 57248
demand_metadata_hits 4 3886139
demand_metadata_misses 4 876962
prefetch_data_hits 4 133147
prefetch_data_misses 4 71927
prefetch_metadata_hits 4 805894
prefetch_metadata_misses 4 94642
mru_hits 4 2334376
mru_ghost_hits 4 9870
mfu_hits 4 12003233
mfu_ghost_hits 4 34745
deleted 4 89041
mutex_miss 4 10
evict_skip 4 239
evict_not_enough 4 2
evict_l2_cached 4 0
evict_l2_eligible 4 14139960320
evict_l2_ineligible 4 3255242752
evict_l2_skip 4 0
hash_elements 4 554684
hash_elements_max 4 568778
hash_collisions 4 424785
hash_chains 4 33824
hash_chain_max 4 5
p 4 3482926902
c 4 11779217520
c_min 4 33554432
c_max 4 16847226880
size 4 11717468560
hdr_size 4 226991968
data_size 4 8517812736
metadata_size 4 1503463424
other_size 4 1469200432
anon_size 4 11872256
anon_evictable_data 4 0
anon_evictable_metadata 4 0
mru_size 4 2606045184
mru_evictable_data 4 1947246592
mru_evictable_metadata 4 39131136
mru_ghost_size 4 7123638784
mru_ghost_evictable_data 4 6026175488
mru_ghost_evictable_metadata 4 1097463296
mfu_size 4 7403358720
mfu_evictable_data 4 6570566144
mfu_evictable_metadata 4 378443776
mfu_ghost_size 4 598224896
mfu_ghost_evictable_data 4 589954048
mfu_ghost_evictable_metadata 4 8270848
l2_hits 4 0
l2_misses 4 0
l2_feeds 4 0
l2_rw_clash 4 0
l2_read_bytes 4 0
l2_write_bytes 4 0
l2_writes_sent 4 0
l2_writes_done 4 0
l2_writes_error 4 0
l2_writes_lock_retry 4 0
l2_evict_lock_retry 4 0
l2_evict_reading 4 0
l2_evict_l1cached 4 0
l2_free_on_write 4 0
l2_cdata_free_on_write 4 0
l2_abort_lowmem 4 0
l2_cksum_bad 4 0
l2_io_error 4 0
l2_size 4 0
l2_asize 4 0
l2_hdr_size 4 0
l2_compress_successes 4 0
l2_compress_zeros 4 0
l2_compress_failures 4 0
memory_throttle_count 4 0
duplicate_buffers 4 0
duplicate_buffers_size 4 0
duplicate_reads 4 0
memory_direct_count 4 445
memory_indirect_count 4 3009
arc_no_grow 4 0
arc_tempreserve 4 0
arc_loaned_bytes 4 0
arc_prune 4 0
arc_meta_used 4 3199655824
arc_meta_limit 4 12635420160
arc_meta_max 4 4183324304
arc_meta_min 4 16777216
arc_need_free 4 0
arc_sys_free 4 526475264
我没法理解太多。如果我理解正确的话,它size
应该是 ARC 的大小。但它应该是 11GB。这在我的内存统计中根本就放不下。
更新 2:
我刚刚结束了 Baloo(Kubuntu 下的搜索索引器),现在情况又变得极端了。
Memory Stats ──────────────────────────────────────────────────────────────────────────────────────────────────────────│
│ RAM High Low Swap Page Size=4 KB │
│ Total MB 32133.5 -0.0 -0.0 8195.5 │
│ Free MB 1004.4 -0.0 -0.0 8132.1 │
│ Free Percent 3.1% 100.0% 100.0% 99.2% │
│ MB MB MB │
│ Cached= 3458.4 Active= 7348.9 │
│ Buffers= 177.5 Swapcached= 3.7 Inactive = 2662.9 │
│ Dirty = 2.9 Writeback = 0.0 Mapped = 937.9 │
│ Slab = 5526.4 Commit_AS = 13320.6 PageTables= 89.2 │
│───────────────────────────────────────────────────────────
现在我缺少 6.5GB!! 的 RAM。
在我结束 Baloo 进程之前,它使用了 3.5Gb。
KDE 是不是在这里使用了一些卑鄙的伎俩?
更新 3
情况变得更糟了。我在另一台 Linux PC 上进行了测试,很明显Inactive used
混入了缓存。所以我丢失了更多内存。
解决方案和后续想法
正如 Silvio Massina 接受的答案所指出的那样,它确实是 ZFS 的 ARC。
现在它声称已分配14GB内存。
cat /proc/spl/kstat/zfs/arcstats | grep -E "^size"
size 4 14953847480
因此我习惯于stress
grep 10 GB 的内存:
stress --vm-bytes 10000000000 --vm-keep -m 1
瞧,ARC 缓存值确实下降了
cat /proc/spl/kstat/zfs/arcstats | grep -E "^size"
size 4 4147553616
现在,在终止之后,stress
我有 11GB 的可用内存,但随着时间的推移,这些内存又被 ARC 慢慢吞噬了。(这完全没问题)
因此 ARC 类似于缓存,但显示在used
内存下,并且不与进程一起列出,只在其自己的信息文件中列出。这对我来说很奇怪,因为我认为操作系统应该始终是内存的主人,应该让人们知道谁使用它。我确实在询问Ubuntu如果你们其中有人感兴趣的话。
附言:如果这对你也有帮助,请不要忘记给我点赞。赏金可不便宜G
答案1
ZFS 使用 ARC(自适应替换缓存)。
来自 Gentoo wiki:
Linux 统计 ARC 使用的内存的方式与页面缓存使用的内存的方式不同。具体来说,在 free 程序使用的输出中,ARC 使用的内存包含在“已使用”而不是“缓存”中。这绝不会阻止在系统内存不足时释放内存。但是,它给人的印象是,如果有机会,ARC(以及 ZFS)将使用所有系统内存。
ARC 使用的内存量取决于系统上可用的内存,可以通过设置 zfs_arc_min 和 zfs_arc_max 参数来控制。
您可以在运行时使用以下命令设置 zfs_arc_max 的值:
echo 2147483648 >> /sys/module/zfs/parameters/zfs_arc_max
或者在启动时使用:
echo "options zfs zfs_arc_max=2147483648" >> /etc/modprobe.d/zfs.conf
值以字节表示。