Дефрагментация распределителя кучи C++ & STL

Я хочу написать self defragmenting memory manager, в котором простой увеличивающий распределитель кучи используется в сочетании с простым уплотнительным дефрагментатором.

грубая схема состояла бы в том, чтобы выделять блоки, начиная с самого низкого адреса памяти, идущего вверх, и вести учет информации, начиная с самого высокого адреса памяти, работающего вниз.

менеджер памяти будет передавать обратно смарт-указатели-boost's intrusive_ptr кажется наиболее очевидно для бухгалтерских структур, которые затем сами указывают на фактический блок памяти, тем самым давая уровень косвенности, чтобы блоки можно было легко перемещать.

дефрагментатор будет сжимать кучу, начиная с закладок "generation", чтобы ускорить процесс и только дефрагментировать фиксированный объем памяти за раз. Необработанные указатели на сами блоки будут действительны до следующего прохода дефрагментации и поэтому могут свободно передаваться до такого времени увеличение производительности.

специфическое применение для этого Программирование консольной игры и поэтому в начале или конце каждого кадра пропуск дефрагментации смог быть сделан относительно безопасно.

поэтому мой вопрос в том, кто-нибудь использовал такую схему распределения в сочетании с STL, просто полностью взорвал бы STL, как я подозреваю. Я вижу, что std:: list работает на уровне intrusive_ptr, но как насчет выделения самих узлов списка stl в любом случае, чтобы переопределить следующие / prev указатели, чтобы быть intrusive_ptr сами или я просто должен иметь стандартный распределитель кучи вдоль этой более динамической.

5 ответов


Если вы собираетесь перемещать объекты в памяти, то вы не можете сделать это полностью обобщенно. Вы сможете сделать это только с объектами, которые знаю что они могут быть перемещены. Вам также понадобится запирающий механизм. Когда функция вызывается на объекте, она не может быть перемещена.

причина в том, что вся модель C++ полагается на объекты, сидящие в фиксированных точках в памяти, поэтому, если поток вызывал метод на объекте, этот поток был приостановлен и объект двигался, катастрофа обрушится, когда нить возобновится.

любой объект, содержащий необработанный указатель памяти на другой объект, который может быть перемещен (включая подобъект), не будет работать.

такая схема управления памятью могут работать, но вы должны быть очень осторожны. Вы должны быть строги в отношении реализации дескрипторов и семантики блокировки указателя handle ->.

для контейнеров STL вы можете настроить распределитель, но он все равно должен возврат исправленных указателей необработанной памяти. Вы не можете вернуть адрес, который может двигаться. По этой причине, если вы используете контейнеры STL, они должны быть контейнерами дескрипторов, а сами узлы будут обычной динамически выделенной памятью. Вы можете обнаружить, что вы слишком много накладных расходов в косвенном обращении дескриптора и все еще имеете проблемы в фрагментации коллекций дескрипторов, чем вы получаете с помощью STL.

использование контейнеров, которые понимают ваши ручки напрямую может быть единственным способом вперед, и даже тогда может быть много накладных расходов по сравнению с приложением c++, которое использует традиционные объекты, фиксированные в памяти.


контейнеры STL реализованы с использованием голых указателей.

вы можете указать пользовательский распределитель при их создании (чтобы они инициализировали свои указатели с помощью вашего распределителя), но (поскольку выделенные значения хранятся в голых указателях) вы не знаете, где эти указатели, и поэтому вы не можете изменить их позже.

вместо этого вы можете рассмотреть возможность реализации подмножества STL самостоятельно: ваши версии контейнеров STL могут быть реализовано с управляемыми указателями.


альтернативной техникой, которая довольно хорошо известна, является система buddy. Вы должны взглянуть на это для дополнительного вдохновения.


Если это для программирования консольных игр, намного проще запретить выделение динамической памяти Без области во время выполнения. И во время запуска, но это немного трудно достичь.


список-исключительно плохой пример для включения менеджер дефрагментации памяти, потому что это куча крошечных кусочков, как и большинство других структур данных STL. Если вы это сделаете, это будет иметь все виды очевидных плохих последствий - включая производительность вашего дефрагментатора, а также косвенную стоимость и т. д. Единственные структуры, в которых ИМО имеет смысл, - это смежные-массив, дека, основной кусок хэш-таблицы, эти вещи, и только за пределами определенного размера, и только после того, как они больше не будут изменены. Такие вещи снова вызовите конкретные решения вместо общих.

прокомментируйте, как все это получается.