вопросы о пуле памяти - PullRequest
6 голосов
/ 19 июля 2011

Мне нужны некоторые пояснения для концепции и реализации пула памяти.

В пуле памяти на вики говорится, что

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

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

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

Что ж, я могу представить, что это хорошо работает для массива примитивных данных.Как насчет C ++ непримитивных классов данных, в которых модель памяти не так очевидна?Даже для примитивных данных разработчик должен учитывать выравнивание типов данных?

Есть ли хорошая библиотека пула памяти для C и C ++?

Спасибо за любые комментарии!

Ответы [ 5 ]

12 голосов
/ 19 июля 2011

Переменный размер блока действительно вызывает фрагментацию. Посмотрите на картинку, которую я прилагаю: enter image description here

Изображение ( отсюда ) показывает ситуацию, в которой A, B и C выделяют порции памяти, порции переменного размера.

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

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

Пулы памяти, конечно, имеют свои недостатки, как вы сами указываете. Так что не стоит думать, что пул памяти - это волшебная палочка. Это имеет свою стоимость, и имеет смысл платить ее при определенных обстоятельствах (например, встроенная система с ограниченной памятью, ограничения в реальном времени и т. Д.).

Что касается того, какой пул памяти хорош в C ++, я бы сказал, что это зависит. Я использовал один под VxWorks, который был предоставлен ОС; в некотором смысле хороший пул памяти эффективен, когда он тесно интегрирован с ОС. На самом деле, каждая RTOS предлагает реализацию пулов памяти, я думаю.

Если вы ищете реализацию общего пула памяти, посмотрите на this .

EDIT:

Из вашего последнего комментария мне кажется, что, возможно, вы думаете о пулах памяти как о "решении" проблемы фрагментации. К сожалению, это не случай. Если вы хотите, фрагментация - это проявление энтропии на уровне памяти, то есть она неизбежна. С другой стороны, пулы памяти - это способ управления памятью таким образом, чтобы эффективно уменьшить влияние фрагментации (как я уже говорил и как упоминалось в Википедии, в основном на конкретных системах, таких как системы реального времени). Это дорого обходится, поскольку пул памяти может быть менее эффективным, чем «нормальный» метод выделения памяти, поскольку у вас минимальный размер блока. Другими словами, энтропия вновь появляется под маской.

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

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

3 голосов
/ 19 июля 2011

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

В сценарии с блоками переменного размера вы можете получить несколько отдельных свободных блоков с различными размерами.Запрос на блок размером меньше, чем общая свободная память, может быть невозможно удовлетворить, потому что нет одного достаточно большого непрерывного блока для него.Например, представьте, что у вас есть два отдельных свободных блока по 2 КБ, и вам нужно удовлетворить запрос на 3 КБ.Ни один из этих блоков не будет достаточным для этого, даже если достаточно памяти.

2 голосов
/ 19 июля 2011

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

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

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

1 голос
/ 19 июля 2011

При использовании пула памяти операции могут работать следующим образом:

  1. Сохранять глобальную переменную, представляющую собой список доступных объектов (изначально пустой).
  2. Чтобы получить новый объектпопробуйте вернуть один из глобального списка доступных.Если его нет, вызовите оператор new, чтобы выделить новый объект в куче.Распределение происходит очень быстро, что важно для некоторых приложений, которые в настоящее время могут тратить много процессорного времени на распределение памяти.
  3. Чтобы освободить объект, просто добавьте его в глобальный список доступных объектов.Вы можете ограничить количество элементов, разрешенных в глобальном списке;если ограничение достигнуто, то объект будет освобожден, а не возвращен в список.Крышка предотвращает появление массовой утечки памяти.

Обратите внимание, что это всегда делается для одного типа данных одинакового размера;это не работает для больших, и тогда вам, вероятно, нужно использовать кучу как обычно.

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

1 голос
/ 19 июля 2011

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

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

Безумно дорого, но работал на оборону.


Когда у вас есть несколько пулов фиксированного размера, вы можете получить вторичную фрагментацию, когда ваш пул вне блоков, даже если в каком-то другом пуле достаточно места. Как вы это делите?

...