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





Возможно, это неправильный подход к тому, о чем вы спрашиваете, но, возможно, можно было бы использовать совсем другую тактику. Если вы ищете действительно быстрый распределитель памяти, возможно, вам стоит спросить, почему вам нужно тратить все это время на выделение памяти, когда вы, возможно, могли бы просто уйти с распределением переменных в стеке. Распределение стека, хотя и более утомительное, но правильное, может сэкономить вам много средств на конфликте мьютексов, а также избавить ваш код от странных проблем с повреждением памяти. Кроме того, у вас потенциально будет меньше фрагментации, которая может помочь.
Если это многопоточная среда, выделение стека подходит только для очень маленьких объектов в небольших количествах - вы не хотите увеличивать размер стека в потоке, потому что тогда вы получите ту же проблему, что и обычное повреждение памяти.
Ага, я согласен с hazzen. Распределение стека, включая локальное хранилище потока, может привести к повреждению памяти, если вы имеете дело с большими или огромными размерами данных.
Мы использовали Hoard в проекте, над которым я работал несколько лет назад. Казалось, это отлично работает. У меня нет опыта работы с другими распределителями. Должно быть довольно легко попробовать разные и провести нагрузочное тестирование, не так ли?
Я использовал tcmalloc и читал о Hoard. Оба имеют похожие реализации, и оба достигают примерно линейного масштабирования производительности по отношению к количеству потоков / процессоров (согласно графикам на соответствующих сайтах).
Итак: если производительность действительно настолько важна, проведите тестирование производительности / нагрузки. В противном случае просто бросьте кубик и выберите один из перечисленных (с учетом простоты использования на вашей целевой платформе).
А из ссылка Тршива похоже, что Hoard, tcmalloc и ptmalloc примерно сопоставимы по скорости. В целом tt выглядит так, как будто ptmalloc оптимизирован для того, чтобы занимать как можно меньше места, Hoard оптимизирован для компромисса между скоростью и использованием памяти, а tcmalloc оптимизирован для чистой скорости.
Ссылка trshiv сейчас здесь
Обе ссылки сейчас не работают
Я лично предпочитаю и рекомендую ptmalloc как многопоточный распределитель. Hoard - это хорошо, но в оценке, которую моя команда провела между Hoard и ptmalloc несколько лет назад, ptmalloc был лучше. Насколько мне известно, ptmalloc существует уже несколько лет и довольно широко используется в качестве многопоточного распределителя.
Вы можете найти это сравнение полезным.
Связанная статья перемещена здесь.
Единственный способ действительно определить, какой распределитель памяти подходит для вашего приложения, - это попробовать несколько. Все упомянутые распределители были написаны умными людьми и превзойдут другие в том или ином микробенчмарке. Если все, что ваше приложение делает в течение всего дня, - это malloc один 8-байтовый фрагмент в потоке A и освобождает его в потоке B, и ему вообще не нужно обрабатывать что-либо еще, вы, вероятно, могли бы написать распределитель памяти, который отбивает штаны от любого из перечисленные до сих пор. Это просто не будет очень полезно для чего-то другого. :)
У меня есть некоторый опыт использования Hoard там, где я работаю (достаточно, чтобы одна из наиболее неясных ошибок, исправленных в недавнем выпуске 3.8, была обнаружена в результате этого опыта). Это очень хороший распределитель, но насколько он хорош для вас, зависит от вашей рабочей нагрузки. И вам действительно нужно заплатить за Hoard (хотя это не слишком дорого), чтобы использовать его в коммерческом проекте без использования вашего кода под лицензией GPL.
Очень немного адаптированный ptmalloc2 уже довольно давно является распределителем памяти malloc в glibc, поэтому он невероятно широко используется и тестируется. Если стабильность важна превыше всего, это может быть хорошим выбором, но вы не упомянули об этом в своем списке, поэтому я предполагаю, что это не так. Для определенных рабочих нагрузок это ужасно, но то же самое можно сказать и о любом malloc общего назначения.
Если вы готовы за это платить (а цена разумная, по моему опыту), SmartHeap SMP также является хорошим выбором. Большинство других упомянутых распределителей разработаны как вставные замены malloc / free new / delete, которые могут быть выполнены с помощью LD_PRELOAD. SmartHeap можно использовать и таким образом, но он также включает в себя весь API, связанный с распределением, который позволяет вам точно настраивать ваши распределители в соответствии с вашими пожеланиями. В проведенных нами тестах (опять же, очень специфичных для конкретного приложения) SmartHeap был примерно таким же, как и Hoard, когда выступал в качестве замены вставляемого malloc; реальная разница между ними - степень настройки. Чем менее универсальным будет ваш распределитель, тем выше будет производительность.
И в зависимости от вашего варианта использования многопоточный распределитель общего назначения может быть совсем не тем, что вы хотите использовать; если вы постоянно выделяете и освобождаете объекты одинакового размера, вы можете просто написать простой распределитель slab. Распределение Slab используется в нескольких местах ядра Linux, которые соответствуют этому описанию. (Я бы дал вам еще пару полезных ссылок, но я «новый пользователь», и Stack Overflow решил, что новым пользователям не разрешается быть полезным тоже в одном ответе. Тем не менее, Google может помочь достаточно хорошо.)
Возможно запоздалый ответ на ваш вопрос, но
Зачем делать маллоки, если у вас резко падает производительность?
Лучшим способом было бы выполнить malloc большого окна памяти при инициализации, а затем придумать light weight Memory manager, который будет lease out the memory chunks at run time.
Это позволяет избежать любых системных вызовов при расширении кучи.
Вы можете попробовать ltalloc (распределитель глобальной памяти общего назначения со скоростью быстрого распределителя пула).
Распределитель locklessinc очень хорош, и разработчик всегда готов ответить, если у вас возникнут вопросы. Есть статья, которую он написал о некоторых используемых приемах оптимизации, это интересное чтение: http://locklessinc.com/articles/allocator_tricks/. Я использовал его в прошлом с отличными результатами.

Какие конкретные проблемы вы пытаетесь решить с помощью текущего диспетчера кучи по умолчанию, который вы используете? И что это?