Я выделяю большой пул памяти из ОСРВ (я уже знаю требования к памяти моего приложения, он не будет превышать определенного размера). И тогда мои запросы на размещение приложений выполняются из этого пула.
Недавно я столкнулся с проблемой; запрос на выделение ресурсов не был выполнен, хотя память была там (получил интегрированную платформу для оценки производительности памяти, которая показала это), расследование показывает, что мы страдаем от фрагментации памяти.
Мое приложение сильно зависит от STL (также получать данные из сети, анализ XML, манипулирование изображениями, сохранять их как PNG и т. Д.), А также как выделение кучи памяти за фрагментацией памяти (есть ли другие причины?). Как лучше всего избегать Это?
Типичная причина фрагментации памяти заключается в том, что с возрастом пула большие блоки памяти разделяются на более мелкие куски. Простой способ избежать этого — иметь фиксированные размеры.
Это явно не решает проблему использования 18 МБ хранилища для XML, где каждый узел XML хранится в виде небольшой строки, а затем попытки загрузки PNG 4096 x 4096 x 8 бит (16 МБ), если ваш пул составляет 24 МБ, потому что XML разделит вашу память на крошечные биты, а затем вам потребуется 16 МБ непрерывной памяти. Но «фиксированные размеры» позволят избежать строки XML <aaa>b</aaa>
занимают 4 байта и 2 байта памяти, что делает память совершенно бесполезной для всего, что там когда-либо хранится, поскольку ни один другой объект не имеет длины 4 или 2 байта.
Этот метод потребует, чтобы ваш распределитель памяти как таковой был написан с учетом «фиксированных размеров».
Первым шагом было бы посмотреть, предоставляет ли ОСРВ какой-либо механизм для куч с низкой фрагментацией.
Если нет, посмотрите, не реализовал ли кто-то еще распределитель с низкой фрагментацией. связанный вопрос (с правой стороны панели) предлагает пример.
В-третьих, если никакое другое существующее решение не работает, решение будет использовать несколько пулов памяти для выделения.
Служебные недолговечные распределения размера от 1 до X байтов из одного пула и долгоживущие выделения размера от 1 до X байтов из другого.
Аналогично для распределений размера X + 1 до 2X, от 2X +1 до 4X, от 4X + 1 до 8X и так далее. (Вы можете экспериментировать с другими размерами ведра …)
Чтобы определить наилучший размер для X, вам нужно будет профилировать свое приложение и видеть частоту каждого размера выделения.
Убедитесь, что в каждом сегменте достаточно места для выполнения выделений 🙂
Гипотетически: переключиться на сборку мусора. Вам нужен компактный сборщик мусора, который может физически перемещаться по выделенным данным, иначе он не поможет с фрагментацией.
free
а также delete
довольно дорогие операции тоже.К сожалению, все это является гипотетическим, так как в настоящее время я не знаю ни одного сжатия, инкрементного сборщика мусора для C ++. За исключением, может быть, C ++ / CLI.