Что такое фрагментация памяти? - PullRequest
181 голосов
/ 22 сентября 2010

Я слышал, как термин «фрагментация памяти» несколько раз использовался в контексте динамического выделения памяти в C ++.Я нашел несколько вопросов о том, как бороться с фрагментацией памяти, но не могу найти прямой вопрос, который касается самой этой проблемы.Итак:

  • Что такое фрагментация памяти?
  • Как узнать, является ли фрагментация памяти проблемой для моего приложения?Какая программа чаще всего страдает?
  • Каковы распространенные способы борьбы с фрагментацией памяти?

Также:

  • Использование динамических распределений может привести к фрагментации памяти.Это правда?Я понимаю, что в контексте C ++ все стандартные контейнеры (std :: string, std :: vector и т. Д.) Используют динамическое распределение памяти.Если они используются во всей программе (особенно в std :: string), является ли проблема фрагментации памяти более вероятной?
  • Как можно решить проблему фрагментации памяти в приложениях с интенсивным использованием STL?*

Ответы [ 11 ]

1 голос
/ 22 сентября 2010

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

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

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

Что следует помнить, так это то, что в 32-битной настольной системе x86 у вас есть целых 2 ГБ памяти, которая разделена на 4 КБ «страницы» (почти уверен, что размер страницы одинаков во всех системах x86). Вы должны будете вызвать некоторую фрагментацию omgwtfbbq, чтобы иметь проблему. Фрагментация на самом деле является проблемой прошлого, поскольку современные кучи чрезмерно велики для подавляющего большинства приложений, и существует преобладание систем, способных противостоять ей, таких как управляемые кучи.

...