您的系统似乎遇到了问题内存碎片严重,可能是因为您正在运行没有任何交换的旧内核。
重要的几行如下:
systemd invoked oom-killer: gfp_mask=0x3000d0, order=2, oom_score_adj=0
...
Node 0 Normal: 1280224*4kB (EM) 188481*8kB (EM) 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 6628744kB
最后一位数字为gfp_mask
是零,所以这个分配需要从Normal
内存区域。这order=2
表示需要分配的数量为 pagesize * 2 ^ order 或 4096 字节 * 2 * 2 = 16 kB。
“buddyinfo”行(您可以使用以下命令检查当前状态cat /proc/buddyinfo
)告诉您在不同的块大小下有多少可用内存。事实证明,您有 1280224 个每个 4 kB 的块、188481 个每个 8 kB 的块以及零个更大的块。该请求是针对 16 kB 块,而您可用的块数为零,因此系统进入 OOM 模式。 (您的系统可能正在运行一些会导致严重碎片的软件,因为这不是具有如此多可用内存的通常状态。)
此外,普通区域中的总可用 RAM 为 6628744 kB,而不是您想象的 9 GB。差异可能是由于您的内存统计记录器无法正确处理内存使用量峰值造成的。
如果您至少使用了少量的交换,我认为内核可以使用它来交换页面,以将一些小页面片段合并为更大的片段,但您已经通过根本没有交换来消除了这种可能性。我建议使用小zram
交换区域,以便在交换时您的性能不受 SSD 或 HDD 的限制。
作为替代方案,您可以尝试运行支持内存压缩的更现代的内核(CONFIG_COMPACTION=y
),您可以按如下方式配置您的系统:
/proc/sys/vm/extfrag_threshold
: 至少500
,最好更多/proc/sys/vm/watermark_scale_factor
: 至少100
,最好更多/proc/sys/vm/zone_reclaim_mode
: 至少1
我会推荐3
or 7
(请注意,如果您正在运行硬实时,则无法更改此设置,但也不应该耗尽 RAM)
您还可以考虑设置/proc/sys/vm/watermark_boost_factor
为大于零的值,但请先阅读文档。
虚拟内存管理器配置选项记录在https://github.com/torvalds/linux/blob/master/Documentation/admin-guide/sysctl/vm.rst https://github.com/torvalds/linux/blob/master/Documentation/admin-guide/sysctl/vm.rst(忽略声称此文档仅版本 2.6.29 的标头,它实际上描述了最新的 Linux 内核)。
或者,如果这种情况仅在系统运行很长时间时发生,则可以通过运行cron
以 root 身份定期运行的作业echo 1 > /proc/sys/vm/compact_memory
.
如果您正在运行的软件支持大页面,您可能需要设置/proc/sys/vm/nr_overcommit_hugepages
大约占 RAM 的 90%。实际上,在 Linux 上你可以简单地运行
echo "$(getconf _PHYS_PAGES) * 0.9 / 512" | bc > /proc/sys/vm/nr_overcommit_hugepages
因为每个大页面为 2 MB,比默认的 4 KB 页面大 512 倍,并且您希望将限制设置为可用物理页面的 90%。对需要大量共享 RAM 的进程(例如 PostgreSQL)使用大页面可以减少内存碎片并减少页表上浪费的 RAM。请注意,这是一个运行时更改,您必须在每次重新启动后执行此操作,然后才能启动支持使用大页面的服务。