首先,我想请求您帮助教我如何编写一个可以触发直接内存回收的程序。
我编写了一个利用 mmap 分配内存的程序,如下所示。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#define PAGE_SZ 4096
#define GB (1<<30)
int random_number(int min, int max) {
return min + rand() % (max - min + 1);
}
int main(int argc, char** argv) {
size_t size;
size = 5ul * GB;
printf("size %lu\n",size);
void *mem = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (mem == MAP_FAILED) {
perror("mmap");
exit(EXIT_FAILURE);
}
size_t num_pages = size / PAGE_SZ;
size_t i;
for (i = 0; i < num_pages; i++) {
*((char *)mem + i * PAGE_SZ) = '6';
}
srand(time(NULL));
while (1) {
size_t random_page = random_number(0, num_pages - 1);
char first_byte = *((char *)mem + random_page * PAGE_SZ);
}
return 0;
}
然而,我注意到只有可用场减少了,而自由场并没有表现出明显的减少。这使得很难触发直接内存回收。
所以我想知道如何让空闲字段和可用字段同时减少?
我非常感谢任何关于如何编写可以有效触发直接内存回收的测试程序的建议或建议。
我想进行这个测试的原因如下。
最近,我的服务器出现了几次挂起的情况,持续时间从几秒到甚至十分钟不等。
我们推出了一个程序来监视处于“D”状态的进程的调用跟踪和内存状态。
首先让我解释一下我在悬挂期间发现的情况。
- 有许多处于“D”状态的进程具有类似的调用跟踪:page_fault->...->filmap_fault()->__lock_page_or_retry()->io_schedule()。 __alloc_page_slowpath 中没有挂起任何进程。
- 通过每 2 秒监控 /proc/vmstat 中 pgsteal_direct 变化的日志记录,系统触发了直接内存回收。变化幅度可以是几千万甚至千万。
- 在直接回收发生之前和之后,“free -h”的可用字段和空闲字段分别为 15GB 和 2GB。
这是有关服务器的一些信息。服务器有128GB内存。 /proc/sys/vm/min_free_kbytes 的值设置为 2GB。交换文件被禁用。
根据这些信息,我认为:
- 有些进程触发了直接回收但没有挂起。
- 直接回收驱逐了一些属于其他进程的页面。 (据我所知,直接回收只会在发生时驱逐干净的页面。)
- 一组进程触发页面错误,导致系统负载过高并导致卡住。
为了验证我的假设,我需要重现直接回收。