Меня интересует тип управления памятью, которую может использовать игра, такая как GTA IV, с учетом того, что ей нужно очень быстро создавать и удалять множество объектов. Как избежать фрагментации кучи и других вещей. Если бы кто-то мог указать мне в правильном направлении, я бы очень признателен.
Как игры, подобные GTA IV, не фрагментируют кучу?
Ответ 1
Они используют такие вещи, как пул памяти, специализированные распределители и специализированные классы контейнеров.
- Распределитель Hoard Memory для многопоточных программ.
- версия EA STL. Содержит распределители, контейнеры,
Ответ 2
Хотя этот документ специально не относится к играм, он обеспечивает хороший обзор типов специализированных распределителей памяти, которые люди часто используют в приложениях C и С++ для повышения производительности (и это немного предостерегающая история).
Пересмотр пользовательского распределения памяти, Бергер, Цорн и Мак-Кинли, OOPSLA 2002
Программисты, надеющиеся добиться повышения производительности, часто используют специализированные распределители памяти. В этом углубленном исследовании рассматриваются восемь приложений, которые используют пользовательские распределители. Удивительно, но для шести из этих приложений, как правило, универсальный распределитель общего назначения (распределитель Lea) работает так же хорошо, как и пользовательские распределители. В двух исключениях используются регионы, которые обеспечивают более высокую производительность (улучшение до 44%). Регионы также уменьшают нагрузку программиста и устраняют утечку памяти. Однако мы показываем, что неспособность программистов освобождать отдельные объекты внутри регионов может привести к значительному увеличению потребления памяти. Хуже того, это ограничение исключает использование регионов для общих идиом программирования, что снижает их полезность. Мы представляем обобщение универсальных и региональных распределителей, которые мы называем пожинать. Reaps представляет собой комбинацию регионов и куч, предоставляя полный диапазон семантики области с добавлением удаления отдельных объектов. Мы показываем, что наша реализация reaps обеспечивает высокую производительность, превосходящую другие распределители с областью, подобной семантике. Затем мы используем тематическое исследование, чтобы продемонстрировать преимущества использования пространства и преимущества разработки программного обеспечения из практики на практике. Наши результаты показывают, что программистам, нуждающимся в быстрых регионах, следует использовать пожинать плоды, и большинство программистов, рассматривающих пользовательские распределители, должны вместо этого использовать распределитель Lea.
Ответ 3
Существуют две очень хорошие реализации malloc
для многопоточных реализаций:
-
tcmalloc
: Google -
jemalloc
: используется Apache (например)
Вот статья в Facebook о улучшении jemalloc. Это примерно в 5 раз быстрее, чем распределитель памяти Hoard в текущем верхнем ответе:)
Ответ 4
Создание и уничтожение множества объектов очень быстро не обязательно означает фрагментацию кучи. Часто, если объекты имеют одинаковый размер, пространство, освобожденное одним, может быть выделено для следующего.
Часто даже в качестве оптимизации программа может не освобождать и удалять память для объектов, а сохранять старые в пуле и просто захватывать одну и перезаписывать содержимое для создания "нового" объекта.
Ответ 5
Я думаю, потому что их объекты в основном имеют одинаковый размер, они могут использовать некоторый менеджер внутренней памяти, который на самом деле не освобождает память, но отмечает его как доступный, а следующий фрагмент размера ~ выделяет его.
Ответ 6
В большинстве игр используются некоторые упомянутые здесь распределители памяти. dlmalloc - это тот, который мы использовали с большим успехом (мы привязали его к Lua). Вы можете получить информацию о dlmalloc здесь.
Еще одна вещь, о которой я бы упомянул, заключается в том, что не все игры должны использовать динамическое распределение памяти. Мы использовали mempool и использовали области статической памяти для большинства наших данных геймплея. Это делают только системы, требующие динамического распределения (Lua и некоторые сторонние библиотеки). Все остальное, что мы делаем, происходит из статических буферов. Мы также не используем STL в gamecode, что помогает ограничить "повреждение" фрагментации памяти.