我的程序有一个自定义分配器,它使用
在以后需要这些页面时调用
这对我来说几乎完美地解决了问题。唯一的问题是,在 MacOS 上,MADV_FREE 很慢地清除了我要求它释放的页面。实际上,只有在另一个应用程序有内存压力时才会清除它们。在清除我释放的页面之前,MacOS 报告我的程序仍在使用该内存;在 Activity Monitor 中,其“实际内存”列不反映已释放的内存。
这使我难以测量我的程序实际使用了多少内存。(无法测量 RSS 正是阻止我们在 10.5 上使用自定义分配器的原因。)
我可以分配大量内存来强制操作系统释放这些页面,但除了需要很长时间外,这可能会产生其他副作用,例如导致我的程序的某些部分被分页到磁盘上。
我试过了
mmap(MAP_ANON | MAP_PRIVATE)
从操作系统获取内存。当不再需要内存时,分配器会调用 munmap
或 madvise(MADV_FREE)
。 MADV_FREE
会保留映射,但告诉操作系统可以丢弃与映射相关联的物理页面。在以后需要这些页面时调用
MADV_FREE
比先调用 munmap
再调用 mmap
更快。这对我来说几乎完美地解决了问题。唯一的问题是,在 MacOS 上,MADV_FREE 很慢地清除了我要求它释放的页面。实际上,只有在另一个应用程序有内存压力时才会清除它们。在清除我释放的页面之前,MacOS 报告我的程序仍在使用该内存;在 Activity Monitor 中,其“实际内存”列不反映已释放的内存。
这使我难以测量我的程序实际使用了多少内存。(无法测量 RSS 正是阻止我们在 10.5 上使用自定义分配器的原因。)
我可以分配大量内存来强制操作系统释放这些页面,但除了需要很长时间外,这可能会产生其他副作用,例如导致我的程序的某些部分被分页到磁盘上。
我试过了
purge
命令,但没有效果。
我如何强制 MacOS 清除这些 MADV_FREE 的页面?或者,我如何询问 MacOS 我的进程中有多少 MADV_FREE 的页面在内存中?
如果有帮助,这是一个测试程序。程序休眠后,Activity Monitor 的“实际内存”列显示为 512MB。在我的 Linux 系统上,top 显示 256MB 的 RSS,正如所期望的那样。#include <sys/mman.h>
#include <stdio.h>
#include <unistd.h>
#define SIZE (512 * 1024 * 1024)
// We use MADV_FREE on Mac and MADV_DONTNEED on Linux.
#ifndef MADV_FREE
#define MADV_FREE MADV_DONTNEED
#endif
int main()
{
char *x = mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
// Touch each page we mmap'ed so it gets a physical page.
int i;
for (i = 0; i < SIZE; i += 1024) {
x[i] = i;
}
madvise(x, SIZE / 2, MADV_FREE);
fprintf(stderr, "Sleeping. Now check my RSS. Hopefully it's %dMB.\n", SIZE / (2 * 1024 * 1024));
sleep(1024);
return 0;
}