У меня есть приложение, которое выделяет много памяти, и я рассматриваю возможность использования лучшего механизма выделения памяти, чем malloc.
Мои основные варианты: jemalloc и tcmalloc. Есть ли преимущества в использовании одного из них перед другим?
В http://locklessinc.com/benchmarks.shtml есть хорошее сравнение между некоторыми механизмами (включая собственный механизм автора - lockless). , и там упоминаются некоторые плюсы и минусы каждого из них.
Учитывая, что оба механизма активны и постоянно совершенствуются. Есть ли у кого-нибудь какие-либо соображения или опыт относительно относительной производительности этих двух механизмов?
Недавно я рассмотрел tcmalloc для проекта на работе. Это то, что я заметил:
Значительно улучшена производительность при интенсивном использовании malloc в многопоточной среде. Я использовал его с инструментом на работе, и производительность улучшилась почти вдвое. Причина в том, что в этом инструменте было несколько потоков, выполняющих выделение небольших объектов в критическом цикле. При использовании glibc производительность страдает из-за, я думаю, блокирования разногласий между вызовами malloc / free в разных потоках.
К сожалению, tcmalloc увеличивает объем памяти. Инструмент, о котором я упоминал выше, будет занимать в два или три раза больше памяти (измеряется максимальным размером резидентного набора) Увеличение объема памяти для нас бесполезно, поскольку мы на самом деле ищем способы уменьшить объем памяти.
В конце концов, я решил не использовать tcmalloc, а вместо этого оптимизировать код приложения напрямую: это означает удаление выделений из внутренних циклов, чтобы избежать разногласий по поводу блокировки / освобождения блокировки. (Для любопытных использование формы сжатия вместо использования пулов памяти.)
Урок для вас состоит в том, что вы должны тщательно измерять свое приложение с типичными рабочими нагрузками. Если вы можете позволить себе дополнительное использование памяти, tcmalloc может подойти вам. Если нет, то tcmalloc все еще полезен, чтобы увидеть, что вы получите, избегая частых обращений к распределению памяти между потоками.
Здесь довольно хорошая дискуссия о распределителях:
http://www.reddit.com/r/programming/comments/7o8d9/tcmalloca_faster_malloc_than_glibcs_open_sourced/
Вы также можете рассмотреть возможность использования консервативного сборщика мусора Boehm . По сути, вы заменяете все malloc
в своем исходном коде на GC_malloc
(и т. Д.), И вы не удосуживаетесь позвонить free
. GC от Boehm не выделяет память быстрее, чем malloc (она примерно одинакова или может быть на 30% медленнее), но имеет преимущество в том, что она автоматически обрабатывает бесполезные зоны памяти, что может улучшить вашу программу (и, конечно, облегчить кодирование, так как тебя больше не волнует бесплатное). GC Бема также можно использовать в качестве распределителя C ++.
Если вы действительно думаете, что malloc
слишком медленный (но вам следует проводить тесты; большинство malloc
-й занимает меньше микросекунды), и если вы полностью понимаете поведение вашей программы при распределении, вы можете заменить некоторые malloc- с вашим специальным распределителем (который может, например, получать память из ядра большими порциями, используя mmap
, и управлять памятью самостоятельно). Но я считаю, что делать это - боль. В C ++ у вас есть концепция allocator и std::allocator_traits
, причем большинство стандартных шаблонов контейнеров принимают такой распределитель (см. Также std::allocator
]), например необязательный второй аргумент шаблона для std::vector
и т. д.
Как и предполагали другие, если вы считаете, что malloc
является узким местом, вы можете размещать данные в виде кусков (или с использованием арен) или просто в массиве.
Иногда может помочь реализация специализированного копирующего сборщика мусора (для некоторых ваших данных). Рассмотрим, возможно, MPS .
Но не забывайте, что преждевременная оптимизация - зло , и, пожалуйста, отметьте & amp; профиль вашего приложения, чтобы понять, где именно теряется время.