Опираясь на ответ Тима, я бы лично использовал что-то похожее на BiBOP.
Основная идея проста: использовать пулы фиксированного размера.
В этом есть некоторые уточнения.
Во-первых, размер пулов обычно фиксирован. Это зависит от вашей процедуры распределения, обычно если вы знаете, что ОС, с которой вы работаете на карте, по крайней мере 4 КБ одновременно, когда вы используете malloc, тогда вы используете это значение. Для файла, отображенного в память, вы можете увеличить его.
Преимущество пулов фиксированного размера состоит в том, что он хорошо борется с фрагментацией. Все страницы одинакового размера, вы можете легко перерабатывать пустую страницу размером 256 байт в страницу размером 128 байт.
Все еще существует некоторая фрагментация для больших объектов, которые обычно выделяются за пределами этой системы. Но оно низкое, особенно если вы помещаете большие объекты в кратные размеру страницы, таким образом, память будет легко перерабатываться.
Во-вторых, как обращаться с бассейнами? Использование связанных списков.
Страницы, как правило, нетипизированы (сами по себе), поэтому у вас есть свободный список страниц, на которых можно подготовить новые страницы и поместить "переработанные" страницы.
Для каждой категории размера у вас есть список «занятых» страниц, в которых выделена память. Для каждой страницы вы держите:
- размер выделения (для этой страницы)
- количество выделенных объектов (для проверки на пустоту)
- указатель на первую свободную ячейку
- указатель на предыдущую и следующую страницы (может указывать на «заголовок» списка)
Каждая свободная ячейка сама является указателем (или индексом, в зависимости от вашего размера) на следующую свободную ячейку.
Список «занятых» страниц заданного размера просто управляется:
- при удалении: если вы очистите страницу, затем удалите ее из списка и поместите на переработанные страницы, в противном случае обновите список свободных ячеек этой страницы (примечание: поиск начала текущей страницы обычно простое по модулю действие по адресу)
- при вставке: поиск начинается с заголовка, как только вы обнаружите неполную страницу, переместите ее перед списком (если ее еще нет) и вставьте свой элемент
Эта схема действительно эффективна с точки зрения памяти, только одна страница зарезервирована для индексации.
Для многопоточных / многопроцессорных приложений вам нужно будет добавить синхронизацию (как правило, мьютекс на страницу), чтобы вы могли получить вдохновение от Google tcmalloc (попробуйте найти другую страницу вместо блокировки, используйте поток -локальный кэш, чтобы запомнить, какую страницу вы в последний раз использовали.
Сказав это, вы пробовали Boost.Interprocess? Предоставляет распределители.