2015-06-20 6 views
4

Я пытаюсь отследить проблему распределения памяти, которую я имею в OSX. Если я обычно компилирую и запускаю следующий код, он будет работать довольно быстро.Медленное распределение памяти в OSX

#include <sys/mman.h> 
#define SIZE 8 * 1024 * 1024 

int main(int argc, char const *argv[]) { 
    for (int i = 0; i < 50000; ++i) { 
    mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); 
    } 
    return 0; 
} 

Однако, если я компилирую тот же код, но ссылки на какую-то библиотеку (т.е .: clang -o test test.c -lpcre) он будет случайным образом либо быстро бегать (30мс) или очень медленно (18 секунд).

Обратите внимание, что я даже не пользуюсь библиотекой, просто связывая ее. Я также заметил, что это не происходит с какой-либо библиотекой.

Я запускаю OSX 10.10.3. Есть идеи?

+1

Я могу воспроизвести проблему. Запуск его с помощью 'iprofile -timeprofiler' показывает, что все время тратится на' __mmap' (который вызывается из 'mmap'). И проверка результата 'mmap' показывает, что вызов всегда преуспевает. – Cornstalks

ответ

4

Это просто ошибка в ядре, с которым столкнулись и другие. Код в ядре для поиска неиспользуемого фрагмента адресного пространства для выделения использует неэффективный алгоритм поиска.

Я подозреваю, что причина, по которой это зависит от того, связано ли вы с библиотекой, заключается в том, что динамический загрузчик (dyld) должен отображать такую ​​библиотеку и иногда получает данные о домашнем хозяйстве VM в состояние, которое вызывает неэффективность поиска. Причина, по которой это не происходит при каждом запуске, вероятно, связана с рандомизацией макета адреса (ASLR).

Я рекомендую вам сообщить об ошибке Apple, особенно если у вас хороший простой тестовый пример. (Вероятно, он будет закрыт как дубликат, так как я уверен, что вы не будете первым, кто его зарегистрирует. Тем не менее, каждый новый отчет об ошибке может помочь изолировать его и повысить приоритет в Apple.)

+0

У вас есть какие-либо ссылки на то, с кем столкнулись другие? – mgarciaisaia

+2

Например, в [этой теме] (http://thread.gmane.org/gmane.comp.version-control.git/34741/focus=34746) о реализации 'git'. Есть и другие примеры. Просто выполните сетевой поиск «os x slow mmap» или аналогичный. –

+0

Я заполнил ошибку. Надеюсь, они исправит это в будущем выпуске! Когда такие вещи случаются со мной, я стараюсь думать, что это должно быть то, что я делаю неправильно. Но в этом случае, сузив возможности, кажется, что нет другого выбора, кроме ошибки ядра. – waj

0

Если вы не хотите, чтобы память была инициализирована, было бы более эффективно использовать malloc(), поскольку использование вами mmap() не только выделяет 8 мегабайт памяти для вашего процесса, но и инициализирует его.

На OS X, как таНос() и ММАП() внутренне использовать системный вызов ММАПА() (системный вызов номер 197 - http://www.opensource.apple.com/source/xnu/xnu-1456.1.26/bsd/kern/syscalls.master), который запрашивает ядро ​​для отображения виртуальной памяти в физическую память.

+0

malloc() также должен попросить операционную систему выделять страницы, но это делается в больших кусках. Но в моем случае мне всегда нужно выделять большие буферы для mmap(), которые должны быть более эффективными. На самом деле я пытался использовать malloc(), и он всегда работает очень медленно. У вас есть пример, где malloc() превосходит mmap()? – waj

+2

@waj Я просто немного поработал в этом отношении, и на OS X вы правы, и я отредактировал свой ответ. И mmap(), и malloc() используют системный вызов mmap() внутренне. У меня создалось впечатление, что malloc() будет использовать системный вызов brk() внутри, что просто изменяет размер сегмента данных, но это неверно. – uname01

+0

@waj Это не имеет смысла для malloc() возвращать медленнее mmap() в этом примере, поскольку malloc() не инициализирует выделенную память. Тем не менее, скорость этих функций очень специфична для реализации. – uname01

-3

Несомненно. Вот идея. Все и его собака выделяют память, вызывая malloc. Никто никогда в истории MacOS X никогда не использовал mmap для распределения памяти. Имея это в виду, сделайте предположение, какая функция была оптимизирована до максимума, и для которой дизайнеры MacOS X не заботятся о скорости. Используйте ту, которая была оптимизирована.

+0

В моем случае мне нужно, чтобы страницы памяти были лениво выделены, поэтому я попытался использовать mmap. Я пробовал с обоими, а не просто гадать. Вы знаете какой-то способ назначить пространство виртуальной памяти в OSX без выделения страниц до их использования? – waj

+0

Кстати, хотя мое использование mmap было неправильным, мне все же хотелось бы знать, почему это странно ведет себя, когда я связываюсь с какой-то лирикой. – waj

+1

Вот идея: 'malloc' использует' mmap', поэтому он не должен быть быстрее, чем просто вызвать 'mmap' напрямую. – Cornstalks