Способы избежать фрагментации памяти

Я выделяю большой пул памяти из ОСРВ (я уже знаю требования к памяти моего приложения, он не будет превышать определенного размера). И тогда мои запросы на размещение приложений выполняются из этого пула.

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

Мое приложение сильно зависит от STL (также получать данные из сети, анализ XML, манипулирование изображениями, сохранять их как PNG и т. Д.), А также как выделение кучи памяти за фрагментацией памяти (есть ли другие причины?). Как лучше всего избегать Это?

2

Решение

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

Это явно не решает проблему использования 18 МБ хранилища для XML, где каждый узел XML хранится в виде небольшой строки, а затем попытки загрузки PNG 4096 x 4096 x 8 бит (16 МБ), если ваш пул составляет 24 МБ, потому что XML разделит вашу память на крошечные биты, а затем вам потребуется 16 МБ непрерывной памяти. Но «фиксированные размеры» позволят избежать строки XML <aaa>b</aaa> занимают 4 байта и 2 байта памяти, что делает память совершенно бесполезной для всего, что там когда-либо хранится, поскольку ни один другой объект не имеет длины 4 или 2 байта.

Этот метод потребует, чтобы ваш распределитель памяти как таковой был написан с учетом «фиксированных размеров».

3

Другие решения

Первым шагом было бы посмотреть, предоставляет ли ОСРВ какой-либо механизм для куч с низкой фрагментацией.

Если нет, посмотрите, не реализовал ли кто-то еще распределитель с низкой фрагментацией. связанный вопрос (с правой стороны панели) предлагает пример.

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

Служебные недолговечные распределения размера от 1 до X байтов из одного пула и долгоживущие выделения размера от 1 до X байтов из другого.

Аналогично для распределений размера X + 1 до 2X, от 2X +1 до 4X, от 4X + 1 до 8X и так далее. (Вы можете экспериментировать с другими размерами ведра …)

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

Убедитесь, что в каждом сегменте достаточно места для выполнения выделений 🙂

2

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

  • Сборка мусора не обязательно несовместима с требованиями в реальном времени. В режиме реального времени означает, что «ваша система должна гарантировать реакцию в течение определенного срока». Если сборщик мусора работает постепенно и может гарантировать достаточно короткую фазу «держи мир», все в порядке.
  • Производительность современных сборщиков мусора — это еще не все плохо. Люди всегда склонны забывать, что free а также delete довольно дорогие операции тоже.
  • Есть компромиссы со сборкой мусора: самые эффективные из них имеют длительные фазы удержания мира. Те с короткими фазами «держи мир» имеют более низкую общую эффективность.

К сожалению, все это является гипотетическим, так как в настоящее время я не знаю ни одного сжатия, инкрементного сборщика мусора для C ++. За исключением, может быть, C ++ / CLI.

0
По вопросам рекламы [email protected]