Linux内存碎片

有没有办法在linux上检测内存碎片? 这是因为在一些长时间运行的服务器上,我注意到性能下降,只有在重启进程之后,我才看到更好的性能。 当我使用linux巨大的页面支持时,我更注意到这一点 – 在Linux中的巨大页面更容易发生碎片?

我特别看了/ proc / buddyinfo。 我想知道是否有更好的方法(不仅仅是CLI命令本身,任何程序或理论背景都可以)来看待它。

我正在回答linux标签。 我的答案只针对Linux

是的,巨大的页面更容易出现碎片。 内存有两个视图,一个是你的进程获得的(虚拟的)和一个内核pipe理的(真实的)。 任何一个页面越大,将它的邻居分组(并保持)越困难,特别是当你的服务运行在一个也需要支持其他服务的系统上时,默认情况下,分配和写入的方式比它们更多实际上最终使用。

内核的真实授权地址的映射是私有的。 有一个非常好的原因,为什么用户空间在内核显示它们时会看到它们,因为内核需要能够过载而不会混淆用户空间。 你的过程得到一个很好的,连续的“迪斯尼”的地址空间,忘记了内核实际上在幕后了什么。

在长时间运行的服务器上看到性能下降的原因很可能是因为已分配的块未被明确locking(例如mlock() / mlockall()posix_madvise() ),并且在一段时间内未被修改,这意味着您服务在必须读取时跳到磁盘。 修改这个行为会使你的进程成为一个坏邻居 ,这就是为什么很多人把他们的RDBMS放在一个完全不同于web / php / python / ruby​​ /的服务器上。 唯一的办法就是减less连续块的竞争。

当页面A在内存中并且页面B已经移动交换时,碎片只是真正引人注意的(在大多数情况下)。 当然,重新开始你的服务似乎是“治愈”了这一点,但仅仅是因为内核还没有机会在超负荷比率的范围内分配过程(现在)新分配的块。

事实上,在高负载下重新启动(可以说)“apache”可能会将其他服务拥有的块直接发送到磁盘。 所以是的,'apache'会在短时间内得到改善,但是'mysql'可能会受到影响,至less在内核缺乏足够的物理内存的情况下,它们会遭受同样的痛苦。

添加更多的内存,或分裂要求malloc()消费者:)它不只是碎片,你需要看看。

尝试使用vmstat来获得实际存储位置的概览。

使用巨大的页面不应该在Linux上造成额外的内存碎片; Linux对大页面的支持只适用于共享内存(通过shmget或mmap),任何使用的大页面都必须被系统pipe理员明确请求和预先分配。 一旦在内存中,他们被钉在那里,并没有换出来。 面对内存碎片交换巨大页面的挑战正是为什么它们仍然固定在内存中(当分配2MB大页面时,内核必须find512个连续的空闲4KB页面,这甚至可能不存在)。

大型网页上的Linux文档: http : //lwn.net/Articles/375098/

有一种情况是内存碎片可能导致巨大的页面分配变慢(但不是巨大的页面导致内存碎片的地方),这就是如果您的系统被configuration为在应用程序请求的情况下增长巨大页面池。 如果/ proc / sys / vm / nr_overcommit_hugepages大于/ proc / sys / vm / nr_hugepages,则可能发生这种情况。

核心

要获得当前碎片索引,请使用:

 sudo cat /sys/kernel/debug/extfrag/extfrag_index 

内核内存碎片整理尝试执行:

 sysctl vm.compact_memory=1 

您也尝试closures透明巨大页面(又名THP)和/或禁用交换(或减lessswappiness )。

用户空间

为了减less用户空间碎片,你可能想尝试不同的分配器,例如jemalloc (它具有很好的自检能力 ,这会给你一个分配器内部碎片的内部)。

您可以通过重新编译程序来切换到自定义malloc,或者只需通过LD_PRELOAD运行程序: LD_PRELOAD=${JEMALLOC_PATH}/lib/libjemalloc.so.1 app (注意THP和内存内存分配器之间的交互 )

尽pipe与内存碎片(但与内存压缩/迁移有关)略有不同,但您可能希望运行多个服务实例,每个NUMA节点一个,并使用numactl绑定它们。