Сравнение производительности механизма выделения памяти в C ++ (tcmalloc и jemalloc) - PullRequest
23 голосов
/ 21 октября 2011

У меня есть приложение, которое выделяет много памяти, и я рассматриваю возможность использования лучшего механизма выделения памяти, чем malloc.

Мои основные параметры: jemalloc и tcmalloc. Есть ли какие-либо преимущества в использовании одного из них по сравнению с другим?

В http://locklessinc.com/benchmarks.shtml есть хорошее сравнение между некоторыми механизмами (в том числе авторским механизмом - без блокировки). и в нем упоминаются некоторые плюсы и минусы каждого из них.

Учитывая, что оба механизма активны и постоянно совершенствуются. У кого-нибудь есть понимание или опыт относительно относительной эффективности этих двух?

Ответы [ 6 ]

36 голосов
/ 21 октября 2011

Если я правильно помню, основное отличие было в многопоточных проектах.

Обе библиотеки пытаются разгрузить память, заставляя потоки извлекать память из разных кешей, но у них разные стратегии:

  • jemalloc (используется Facebook) поддерживает кэш на поток
  • tcmalloc (от Google) поддерживает пул кэшей, а потоки развивают «естественную» привязку ккеш, но может измениться

Это привело, еще раз, если я правильно помню, к существенному различию в терминах управления потоками.

  • jemalloc быстрее, если потокистатичны, например, использование пулов
  • tcmalloc быстрее при создании / уничтожении потоков

Существует также проблема, заключающаяся в том, что с jemalloc вращаются новые кэши для размещения нового потокаидентификаторы, имеющие внезапный всплеск потоков, оставят вас с (в основном) пустыми кешами в последующей спокойной фазе.

В результате я бы порекомендовал tcmalloc в общем случае,и зарезервируйте jemalloc для очень специфического использования (низкий разброс количества потоков в течение срока службы приложения).

11 голосов
/ 04 июня 2012

Я недавно рассматривал tcmalloc для проекта на работе.Вот что я наблюдал:

  • Значительно улучшена производительность при интенсивном использовании malloc в многопоточной среде.Я использовал его с инструментом на работе, и производительность улучшилась почти вдвое.Причина в том, что в этом инструменте было несколько потоков, выполняющих выделение небольших объектов в критическом цикле.При использовании glibc производительность страдает из-за, по-моему, блокирования конфликтов между вызовами malloc / free в разных потоках.

  • К сожалению, tcmalloc увеличивает объем используемой памяти.Инструмент, о котором я упоминал выше, будет занимать в два или три раза больше памяти (измеряется максимальным размером резидентного набора).Увеличение объема памяти для нас бесполезно, так как мы на самом деле ищем способы уменьшить объем памяти.

В конце концов я решил не использовать tcmalloc, а вместо этого оптимизировать код приложения напрямую.: это означает удаление распределений из внутренних циклов, чтобы избежать конфликтов блокировки / освобождения.(Для любопытных использование формы сжатия вместо использования пулов памяти.)

Урок для вас состоит в том, что вы должны тщательно измерять свое приложение с типичными рабочими нагрузками.Если вы можете позволить себе дополнительное использование памяти, tcmalloc может подойти вам.Если нет, то tcmalloc все еще полезно, чтобы увидеть, что вы получите, избегая частых обращений к распределению памяти между потоками.

4 голосов
/ 14 августа 2013

Имейте в виду, что согласно домашней странице nedmalloc, современные распределители ОС на самом деле довольно быстрые:

«Windows 7, Linux 3.x, FreeBSD 8, Mac OS X 10.6 содержат современные распределители, и ни один сторонний распределитель вряд ли значительно улучшит их в реальных результатах»

http://www.nedprod.com/programs/portable/nedmalloc

Так что, возможно, вам удастся сойти с рук, просто порекомендовав обновить пользователей или что-то в этом роде:)

1 голос
/ 27 октября 2011

Вы также можете использовать Консервативный сборщик мусора Boehm .По сути, вы заменяете каждый malloc в исходном коде на GC_malloc (и т. Д.), И вы не удосуживаетесь позвонить free.GC от Boehm не выделяет память быстрее, чем malloc (она примерно одинакова или может быть на 30% медленнее), но имеет преимущество в том, что она автоматически обрабатывает бесполезные зоны памяти, что может улучшить вашу программу (и, конечно, облегчить кодирование,так как тебя больше не волнует бесплатное).GC от Boehm также может быть использован в качестве распределителя C ++.

Если вы действительно думаете, что malloc слишком медленный (но вы должны тестировать; большинство malloc -с занимает меньше, чеммикросекунды), и если вы полностью понимаете поведение своей программы при распределении, вы можете заменить некоторые malloc-ы своим специальным распределителем (который может, например, получать память из ядра большими порциями, используя mmap, и управлять памятью самостоятельно.).Но я считаю, что делать это - боль.В C ++ у вас есть концепция allocator и std::allocator_traits, с большинством стандартных контейнеров шаблонов, принимающих такой распределитель (см. Также std::allocator), например, необязательный второй аргумент шаблона для std::vector и т. д. *

Как и другие предполагали, если вы считаете, что malloc является узким местом, вы можете распределять данные порциями(или используя арены), или просто в массиве.

Иногда может помочь реализация специализированного копирования сборщик мусора (для некоторых ваших данных).Подумайте, возможно, MPS .

Но не забывайте, что преждевременная оптимизация - это зло , и, пожалуйста, сравните и профилируйте ваше приложение, чтобы точно понять, где теряется время.

1 голос
/ 21 октября 2011

В вашем посте не упоминается многопоточность, но перед рассмотрением вопроса о смешении методов выделения C и C ++ я бы изучил концепцию пула памяти. У BOOST есть хороший вариант.

1 голос
/ 21 октября 2011

Здесь довольно хорошая дискуссия о распределителях:

http://www.reddit.com/r/programming/comments/7o8d9/tcmalloca_faster_malloc_than_glibcs_open_sourced/

...