Масштабируемое распределение памяти
В настоящее время я оцениваю несколько масштабируемых распределителей памяти, а именно nedmalloc и ptmalloc (оба построены поверх dlmalloc), в качестве замены по умолчанию malloc / new из-за значительного конфликта, наблюдаемого в многопоточной среде. Их опубликованные результаты кажутся хорошими, однако я хотел бы проверить, каков опыт других людей, которые действительно их использовали.
- Были ли ваши цели достигнуты?
- Были ли у вас какие-то неожиданные или сложные проблемы (например, повреждение кучи)?
- Если бы вы попробовали и ptmaalloc, и nedmalloc, какой из них вы бы порекомендовали? Почему (простота использования, производительность)?
- Или, возможно, вы бы порекомендовали другой масштабируемый распределитель (бесплатный с предпочтительной лицензией)?
4 ответа
Я внедрил NedMalloc в наше приложение, и я вполне доволен результатами. Разногласия, которые я видел раньше, исчезли, и к распределителю было довольно легко подключиться, даже общая производительность была очень хорошей, вплоть до того момента, когда накладные расходы на выделение памяти закончились, приложение теперь почти неизмеримо.
Я не пробовал ptmalloc, так как я не нашел его готовую для Windows версию, и я потерял мотивацию, когда NedMalloc работал нормально для меня.
Помимо двух упомянутых, я думаю, что было бы также интересно попробовать TCMalloc - у него есть некоторые функции, которые теоретически звучат лучше, чем NedMalloc (например, очень небольшие накладные расходы для небольших выделений по сравнению с заголовком 4 B, используемым NedMalloc), однако, так как он похоже, что порт Windows не готов, это может оказаться не совсем простым делом.
После нескольких недель использования NedMalloc я был вынужден отказаться от него, потому что его пространство оказалось слишком высоким для нас. Особенно поразило нас то, что NedMalloc, похоже, исправляет память, которую он больше не использует для операционной системы, ненадлежащим образом, сохраняя при этом большую часть своей активности. На данный момент я заменил его на JEMalloc, который, кажется, не такой быстрый (он все еще быстрый, но не такой быстрый, как был NedMalloc), но он очень надежен в этом отношении, и его масштабируемость также очень хороша.
И после нескольких месяцев использования JEMalloc я перешел на TCMalloc. Потребовалось больше усилий, чтобы адаптировать его для Windows по сравнению с другими, но его результаты (как производительность, так и фрагментация) кажутся нам лучшими из того, что я тестировал до сих пор.
В прошлом мне нужен был очень быстрый метод для выделения памяти. Я обнаружил, что не было выделенного ресурса, подходящего для работы.
После нескольких дней поиска я натолкнулся на boost::pool, который в нашем приложении дал увеличение производительности в 300 раз.
Мы просто вызываем malloc/free для объектов, которые хотим создать. Хотя есть небольшие накладные расходы на установку, из-за которых необходимо сначала распределить большой объем памяти, но как только это будет сделано, это очень быстро.
Если вы работаете на Win32, мой опыт показывает, что трудно превзойти обычный диспетчер кучи Windows, если вы включите Low Fragmentation Heap с помощью API HeapSetInformation. Я считаю, что теперь это стандарт на новых версиях Windows. Он обрабатывает блокировку с использованием примитивов Interlocked* Win32, а не более простой блокировки Mutex/CritSec.
Я пытался пойти по вашему пути, когда столкнулся с многопоточным конфликтом и серьезной проблемой фрагментации. После небольшого тестирования я пришел к выводу, что польза от этих распределителей незначительна в большинстве интересных случаев, которые у меня были.
Реальное решение состояло в том, чтобы вытащить свой собственный менеджер памяти, который был специализирован для задач, которые я выполнял чаще всего.