macos - 如何强制 MacOS 释放 MADV_FREE 的页面?

标签 macos memory-management

我的程序有一个自定义分配器,它使用 mmap(MAP_ANON | MAP_PRIVATE) 从操作系统获取内存.当它不再需要内存时,分配器调用 munmapmadvise(MADV_FREE) . MADV_FREE保持映射,但告诉操作系统它可以丢弃与映射关联的物理页面。

调用 MADV_FREE在您最终将再次需要的页面上,比调用 munmap 快得多后来打电话 mmap再次。

这对我来说几乎完美。唯一的问题是,在 MacOS 上,MADV_FREE 对于摆脱我要求它释放的页面非常懒惰。事实上,只有当另一个应用程序有内存压力时,它才会摆脱它们。在它清除我释放的页面之前,MacOS 报告我的程序仍在使用该内存;在事件监视器中,它的“真实内存”列不反射(reflect)释放的内存。

这使我很难衡量我的程序实际使用了多少内存。 (测量 RSS 的难度使我们无法在 10.5 上登陆自定义分配器。)

我可以分配一大堆内存来强制操作系统释放这些页面,但除了花费很长时间之外,这可能会产生其他副作用,例如导致我的程序的一部分被分页到磁盘。

在 lark 上,我尝试了 purge命令,但没有效果。

如何强制 MacOS 清除这些 MADV_FREE 页面?或者,我如何询问 MacOS 我的进程在内存中有多少 MADV_FREE 页面?

这是一个测试程序,如果有帮助的话。程序进入休眠状态后,事件监视器的“真实内存”列显示为 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;
}

最佳答案

mprotect(addr, length, PROT_NONE);
mprotect(addr, length, PROT_READ | PROT_WRITE);

请注意,如您所说,madvise 更懒惰,这可能对性能更好(以防万一有人想将其用于性能而不是测量)。

关于macos - 如何强制 MacOS 释放 MADV_FREE 的页面?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7718964/

相关文章:

Swift - 为什么 NSColor 在渲染时变浅

c++ - lodePNG 内存分配错误

c++ - 如何在驱动程序代码中检查 unsigned char 指针是否为零?

Mac 上的 Chrome 中未加载 CSS

c++ - 在 Mac OS X 上构建 Google Breakpad

c++ - Windows 由于 64 位进程的内存分配过多而死机

c# - Assembly.LoadFrom 加载错误的程序集

c# - 在 C# 和 C++ 代码之间共享对象

python - 未知类型名称 'glp_long' (mac osx python, pyglpk)

linux - 如何使用每个 screen 的自定义命令启动多个 screen ?