Я использую в основном O (1) Small Block Memory Manager (SBMM). В основном это работает так:
1) Он выделяет большие Суперблоки из ОС и отслеживает начальные + конечные адреса как диапазон. Размер SuperBlock регулируется, но 1 МБ делает довольно хороший размер.
2) Суперблоки разбиты на блоки (также регулируемые по размеру ... 4K-64K хорошо в зависимости от вашего приложения). Каждый из этих блоков обрабатывает выделения определенного размера и сохраняет все элементы в блоке в виде односвязного списка. Когда вы выделяете Суперблок, вы создаете связанный список бесплатных блоков.
3) Выделение элемента означает A) Проверка наличия блока со свободными элементами, который обрабатывает этот размер, и, если нет, выделение нового блока из суперблоков. Б) Удаление предмета из списка свободных блоков.
4) Освобождение предмета с помощью адреса означает A) Нахождение суперблока, содержащего адрес (*) B) Нахождение блока в суперблоке (вычтите начальный адрес суперблока и разделите на размер блока) C) Отталкивание предмета назад в списке свободных предметов блока.
Как я уже говорил, этот SBMM очень быстрый, поскольку он работает с производительностью O (1) (*). В реализованной мною версии я использую AtomicSList (похожий на SLIST в Windows), так что это не только производительность O (1), но и ThreadSafe и LockFree в реализации. Вы могли бы на самом деле реализовать алгоритм, используя Win32 SLIST, если хотите.
Интересно, что алгоритм распределения Блоков из Суперблоков или Предметов из Блоков приводит к почти идентичному коду (они оба O (1) выделяют из Свободного Списка).
(*) Суперблоки расположены в карте диапазона с O (1) средней производительностью (но с потенциальным O (Lg N) для наихудшего случая, где N - количество суперблоков). Ширина карты диапазона зависит от того, насколько приблизительно вы знаете, сколько памяти вам понадобится, чтобы получить производительность O (1). Если вы перезапустите, вы потеряете немного памяти, но все равно получите производительность O (1). Если вы не достигли цели, вы приблизитесь к производительности O (Lg N), но N соответствует количеству суперблоков, а не количеству элементов. Поскольку количество суперблоков очень мало по сравнению с количеством элементов (примерно в 20 двоичных порядках величины в моем коде), оно не так критично, как остальная часть распределителя.