Проектирование и кодирование нефрагментирующего статического пула памяти - PullRequest
1 голос
/ 13 октября 2010

Я уже слышал этот термин раньше, и я хотел бы знать, как его спроектировать и написать.
Должен ли я использовать распределитель STL, если он доступен?
Как это можно сделать на устройствах без ОС?
Каковы компромиссы между его использованием и использованием обычного компилятора malloc / new?

Ответы [ 2 ]

3 голосов
/ 13 октября 2010

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

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

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

Более подробную информацию о многопоточных распределителях можно найти здесь .

2 голосов
/ 13 октября 2010

Попробую описать, что по сути является пулом памяти - я просто набираю это на макушке, уже давно, как я его реализовал, если что-то явно глупое, это всего лишь предложение! :)

1. Чтобы уменьшить фрагментацию, вам нужно создать пул памяти, соответствующий типу объекта, который вы в нем размещаете. По сути, вы затем ограничиваете размер каждого выделения до размера интересующего вас объекта. Вы можете реализовать шаблонный класс, который имеет список динамически распределенных блоков (причина в том, что вы можете увеличить объем пространства имеется в наличии). Каждый динамически распределенный блок будет по существу массивом T.

В таком случае у вас будет «свободный» список, представляющий собой односвязный список, в котором заголовок указывает на следующий доступный блок. Распределение тогда просто возвращает голову. Вы можете наложить связанный список в самом блоке, то есть каждый «блок» (который представляет выровненный размер T), по сути, будет объединением T и узла в связанном списке, когда выделен, это T, когда освобожден, узел в списке. Есть очевидные опасности! В качестве альтернативы, вы можете выделить отдельный (и защищенный блок, который добавляет дополнительные издержки) для хранения массива адресов в блоке.

Распределение является тривиальным, перебирает список блоков и выделяет из первых доступных, освобождение также тривиально, дополнительная проверка, которую вы должны сделать, - найти блок, из которого это выделено, и затем обновить указатель заголовка. (обратите внимание, вам нужно будет использовать либо новое место размещения, либо переопределить оператор new / delete в T - есть способы обойти это, Google - ваш друг)

«Статический», как мне кажется, подразумевает пул одноэлементной памяти для всех объектов типа T. Недостатком является то, что для каждого T необходимо иметь отдельный пул памяти. Вы можете быть умным и иметь один объект, который управляет пулами разного размера (например, используя массив указателей для объектов пула, где индекс - это размер объекта).

Весь смысл предыдущего параграфа состоит в том, чтобы точно указать, насколько это сложно, и, как говорит RC выше, убедитесь, что вам это нужно, прежде чем вы это сделаете - так как это может вызвать больше боли, чем может быть необходимо!

2. Если распределитель STL отвечает вашим потребностям, используйте его, он разработан некоторыми очень умными людьми, которые знают, что они делают - однако это для общего случая, и если вы знаете, как распределяются ваши объекты, вы могли бы заставить вышеописанное работать быстрее.

3. Вам нужно как-то распределять память (аппаратная поддержка или HAL - что угодно) - иначе я не уверен, как будет работать ваша программа?

4. Обычный malloc / new делает намного больше вещей под прикрытием (google - твой друг, мой ответ уже является эссе!) Простой распределитель, который я описал выше, не является повторным, конечно, вы можете обернуть его мьютексом для обеспечить немного укрытия, и даже тогда я бы рискнул, что простой распределитель будет выполнять на несколько порядков быстрее, чем обычный malloc / free.

Но если вы находитесь на этом этапе оптимизации - возможно, вы исчерпали возможность оптимизации ваших алгоритмов и использования структуры данных?

...