内存信息

内存信息

我在 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 内存可能需要与可用内存进行比较。

总体而言,这台主机可以使用更多内存。可以使用现有内存,但需要进行更多容量规划,仔细查看正在运行的内容以及限制其资源使用的因素。

相关内容