我在 serverfault 和 linuxatemyram.com 上读过不少关于 RAM 使用情况的文章,但似乎没有一篇能让我深入了解我的机器上发生了什么
top - 17:42:31 up 8 days, 10:23, 3 users, load average: 1.16, 1.14, 1.19
Tasks: 344 total, 1 running, 343 sleeping, 0 stopped, 0 zombie
%Cpu(s): 13.3 us, 2.4 sy, 0.0 ni, 83.4 id, 0.0 wa, 0.0 hi, 0.8 si, 0.0 st
MiB Mem : 15888.2 total, 600.2 free, 14782.2 used, 505.9 buff/cache
MiB Swap: 8192.0 total, 6647.9 free, 1544.1 used. 673.3 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
3959357 howie 20 0 9290724 3.6g 166112 S 44.2 23.2 817:31.05 java
1479873 howie 20 0 20.7g 4.8g 12140 S 14.6 31.1 881:40.81 java
1513 root 20 0 0 0 0 S 4.7 0.0 395:04.70 napi/eth%d-385
1516 root 20 0 0 0 0 S 0.3 0.0 48:38.33 napi/eth%d-386
2548 unifi 20 0 7867536 526756 4416 S 0.3 3.2 36:21.41 java
2713 root 20 0 493312 2216 1312 S 0.3 0.0 3:25.22 X
3285 sddm 20 0 1326628 14908 4932 S 0.3 0.1 10:37.51 .sddm-greeter-w
1239489 root 20 0 0 0 0 I 0.3 0.0 0:00.35 kworker/2:2-events
1332415 howie 20 0 11232 2844 2152 S 0.3 0.0 0:01.09 top
1 root 20 0 168780 5732 3132 S 0.0 0.0 7:48.99 systemd
我的 top 进程使用了大约 55-60% 的内存。如果拥有 16/15.5GI,则预计会有大约 6G 的空闲或可用空间。top 和 free 表示我有大约 541Mb-1Gb 的空闲空间。(顶部截图是在几分钟后拍摄的...)
total used free shared buff/cache available
Mem: 15888 14477 915 34 495 983
Swap: 8191 1544 6647
有人能建议如何找出是否有东西占用了我的 RAM 吗?
cat /proc/meminfo
MemTotal: 16269540 kB
MemFree: 469556 kB
MemAvailable: 681988 kB
Buffers: 0 kB
Cached: 579676 kB
SwapCached: 188676 kB
Active: 7583844 kB
Inactive: 2554720 kB
Active(anon): 7248276 kB
Inactive(anon): 2346652 kB
Active(file): 335568 kB
Inactive(file): 208068 kB
Unevictable: 20576 kB
Mlocked: 0 kB
SwapTotal: 8388604 kB
SwapFree: 6809504 kB
Dirty: 364 kB
Writeback: 0 kB
AnonPages: 9559824 kB
Mapped: 419488 kB
Shmem: 36040 kB
KReclaimable: 79620 kB
Slab: 770456 kB
SReclaimable: 79620 kB
SUnreclaim: 690836 kB
KernelStack: 16696 kB
PageTables: 62508 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 16523372 kB
Committed_AS: 14439856 kB
VmallocTotal: 34359738367 kB
VmallocUsed: 306496 kB
VmallocChunk: 0 kB
Percpu: 2512 kB
AnonHugePages: 2048 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: 12745260 kB
DirectMap2M: 3907584 kB
dmesg 显示 oom-killer 正在工作(仅显示多个条目中的一个......)
dmesg | grep oom-killer
[174151.082274] dockerd invoked oom-killer: gfp_mask=0x140cca(GFP_HIGHUSER_MOVABLE|__GFP_COMP), order=0, oom_score_adj=0
谢谢
答案1
内存信息
是的,您的 meminfo 报告 AnonPages 总共有 15.5 GB,其中 9.1 GB。
少量的 Shmem 和文件页面。这与执行大量私有分配的应用程序一致,并且您确实正在运行一些 java。注意 java 确实不是倾向于直接为 JVM 分配共享内存。与数据库不同,数据库通常具有共享内存段,并且当然会执行大量文件 I/O。
不,您无法使用所有剩余空间。MemAvailable 是对此最有用的估计,而您的空间相对较低,为 0.7 GB,即 MemTotal 的 4%。 上游的笔记这是什么:
可用内存
估计有多少内存可用于启动新应用程序(无需交换)。根据 MemFree、SReclaimable、文件 LRU 列表的大小以及每个区域中的低水位线计算得出。该估计考虑到系统需要一些页面缓存才能正常运行,并且由于项目正在使用中,并非所有可回收的 slab 都可以回收。这些因素的影响因系统而异。
因此,实际上释放内存,并猜测从文件缓存和内核对象中回收页面很容易。很简单。超过此大小的新内存分配可能会导致直接回收速度非常慢,或激怒 oom killer。
一些非常难以从 meminfo 中回收的项目是 SUnreclaim、KernelStack 和 PageTables,总计可能为 0.8 GB。这并非不合理,我倾向于假设一个不小的主机至少需要一到两 GB 的空间用于内核。
仍有 5 GB 左右的空间不易分配。我猜想这些空间在某个时候被使用过,发生了一些变化,例如进程终止,而内核尚未完成将其回收为空闲空间的工作。
容量规划估算
粗略地估算一下此应用程序可以使用的内存量。基于您的使用经验以及其工作大小的大致大小。
Java 的内存使用情况以及限制内存使用的方法都有详尽的记录。Red Hat 开发者博客就此进行了尝试。堆占了大部分,但还有更多: JVM memory = Heap memory+ Metaspace + CodeCache + (ThreadStackSize * Number of Threads) + DirectByteBuffers + Jvm-native
还要注意四舍五入的建议。“生产堆大小应该至少比测试的最大值高出 25% 到 30%,以留出开销空间。”
容器
我觉得很奇怪,dockerd 和其他进程会触发 oom killer,而大型 java 进程显然不会。诚然,oom killer 是基于任意启发式方法进行猜测的。
容器可以通过 cgroups 设置内存使用限制并针对不同组进行调整。还可以准确报告每个 cgroup 的内存使用情况,systemd 系统上的一个好工具是systemd-cgtop -m
检查容器的所有内存相关配置,对于docker参见资源限制文档(尽管该 docker 页面上至少有一件事是不正确的:swappiness 不是百分比。)
确保主机范围内内存不会不足可能意味着设置每个容器的内存限制。如果它们包含一些 Java 线程,则将最大值设置为高于容量规划的估计值。
猜测一下,但可能--oom-kill-disable
是在 Java 容器上。在内存压力大但大消费者受到保护的情况下,oom killer 可能会删除主机上的其他系统进程。在某种程度上,我更希望它删除大 Java 线程,作为对管理员的提示,JVM 内存可能需要与可用内存进行比较。
总体而言,这台主机可以使用更多内存。可以使用现有内存,但需要进行更多容量规划,仔细查看正在运行的内容以及限制其资源使用的因素。