Как заставить MacOS выпускать страницы MADV_FREE? - PullRequest
4 голосов
/ 11 октября 2011

В моей программе есть специальный распределитель, который получает память от ОС с помощью 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'd?Или, как я могу спросить MacOS, сколько страниц MADV_FREE у моего процесса в памяти?

Вот тестовая программа, если она помогает.В столбце «Реальная память» монитора активности отображается 512 МБ после перехода программы в спящий режим.На моем Linux-компьютере top показывает 256 МБ 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;
}

Ответы [ 3 ]

3 голосов
/ 25 января 2012
mprotect(addr, length, PROT_NONE);
mprotect(addr, length, PROT_READ | PROT_WRITE);

Обратите внимание, как вы говорите, madvise более ленив, и это, вероятно, лучше для производительности (на тот случай, если у кого-нибудь возникнет желание использовать это для производительности, а не для измерения).

1 голос
/ 23 ноября 2018

Используйте MADV_FREE_REUSABLE в macOS. Согласно реализации Apple magazine_malloc:

В OS X мы используем MADV_FREE_REUSABLE, который сигнализирует ядру об удалении указанных страниц из статистики памяти для нашего процесса. Однако, возвращая эту память для использования, мы должны сообщить, что она была использована повторно.

https://opensource.apple.com/source/libmalloc/libmalloc-53.1.1/src/magazine_malloc.c.auto.html

Хром, например, также использует его:

MADV_FREE_REUSABLE аналогично MADV_FREE, но также помечает страницы многоразовым битом, что позволяет как Activity Monitor, так и memory-infra правильно отслеживать страницы.

https://github.com/chromium/chromium/blob/master/base/memory/discardable_shared_memory.cc#L377

0 голосов
/ 13 октября 2011

Я посмотрел и посмотрел, и я не думаю, что это возможно.: \

Мы решаем проблему, добавляя код в распределитель, который явно распаковывает страницы MADV_FREE, когда мы его просим.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...