Каковы преимущества и недостатки использования jemalloc против malloc против calloc и других распространенных альтернатив?
Читая сегодня субреддит Rust, я наткнулся на комментарии, которые:
jemalloc оптимизирован для (многопоточной) скорости, а не использования памяти
Проведя дополнительные исследования, я обнаружил, что есть еще больше альтернатив (таких как calloc).
Я хотел бы понять, в чем преимущества и недостатки различных распределителей памяти?
Если этот вопрос кажется глупым, мой фон в основном интерпретируемые языки (которые не предоставляют такого тонкого контроля памяти).
0 ответов
malloc
, calloc
, а также realloc
Эти функции не являются различными распределителями. Это разные способы запроса памяти у одного и того же распределителя.
malloc
обеспечивает память без инициализации (заполняется тем, что в ней хранилось предыдущим пользователем).calloc
такой же какmalloc
но он также будет инициализировать память (заполнить его нулевым байтом0x00
).realloc
занимает уже выделенную память и позволяет пользователям изменять ее размер.
Итак, в контексте распределителей и их различных реализаций, malloc
, calloc
а также realloc
не перечислены независимо, потому что каждая реализация распределителя нуждается в своей собственной версии этих функций.
jemalloc
, ptmalloc
...
Когда кто-то хочет реализовать другой распределитель, он не может (может, но не должен по умолчанию) назвать его malloc
потому что он будет сталкиваться со стандартной библиотекой Си. Вместо этого они обычно дают ему другой префикс, такой как jemalloc, ptmalloc, nedmalloc, tcmalloc и другие.
Стоит отметить, что существует также несколько реализаций самой стандартной библиотеки C, и каждая из них будет реализовывать свой распределитель по-своему. Так malloc
будет иметь другую реализацию в зависимости от того, какая стандартная библиотека используется при компиляции кода. Примеры: Стандартная библиотека GNU C, Стандартная библиотека MSVC и т. Д.
В чем разница между разными распределителями?
Чтобы узнать точные преимущества и недостатки каждой реализации, необходимо прочитать документацию, написанную авторами / авторами каждой из них, если она существует, прочитать код, чтобы понять алгоритм, или прочитать статьи / исследовательские работы, написанные экспертами, которые говорят об этом конкретном реализация.
Однако, если бы я классифицировал различия между этими реализациями, я бы перечислил следующее:
- Некоторые реализации фокусируются на определенных шаблонах использования и пытаются оптимизировать их даже за счет снижения эффективности других случаев. Примером этого может быть
jemalloc
где они сосредоточились на оптимизации распределения из нескольких потоков, чтобы сделать это быстрее, но за счет использования большего количества памяти. Эти типы распределителей обычно развертываются после тщательного расследования конкретного случая, который показал, что он выиграет от этого компромисса. - Некоторые реализации накладывают определенные ограничения на использование распределителя, чтобы сделать его быстрее. Пример - однопоточные распределители, которые устранят необходимость в объектах синхронизации, чтобы сделать это быстрее.
- Другие реализации стараются быть как можно более универсальными и ни в коем случае не отдают предпочтение другим. В эту категорию входят распределители по умолчанию, включенные в стандартные библиотеки.