Я исследовал создание своих собственных методов распределения (которые будут поддерживать такие вещи, как пул памяти и профилирование), однако, продолжая исследование, я искал, как это было сделано в разработке игр.
Какую технику выделения памяти я могу использовать, и почему это хорошая техника?
Ответы:
Архитектура Game Engine имеет некоторую информацию по этой теме. Основы в том, что вам нужно провести некоторый анализ, чтобы понять, каковы ваши требования к памяти на уровень / кадр / и т. Д. похожи, но есть несколько паттернов, которые автор упоминал несколько раз:
Самая большая вещь, на которую автор обращает внимание, это фрагментация памяти. Это не проблема, если вы разрабатываете, например, для ПК, где у вас есть какая-то резервная копия подкачки памяти, на которую вы можете рассчитывать, но в фиксированном контексте памяти, таком как консоль, существует риск «нехватки памяти» при попытке выделить большой объект, потому что ваша память фрагментирована таким образом, что доступны только маленькие непрерывные блоки. С этой целью он рекомендует, чтобы распределитель на основе стека, как указано выше, также включал метод периодической дефрагментации его содержимого.
Для получения дополнительной информации о реальном коде, который в этом задействован, я настоятельно рекомендую статью Кристиана Гирлинга «У нас не хватает памяти?» , которая охватывает методы для пользовательских распределителей, в основном с точки зрения анализа моделей использования памяти, но это также применимо к разработке специального решения для управления памятью.
источник
Из того, что я видел (но не сделал), каждая игра имеет тенденцию либо наследовать механизмы распределения от каркаса, от игрового движка, от предыдущей версии (2010 -> 2011), либо получать набор новых, написанных специально для ее структура (либо когда структуры данных могут быть повторно использованы и имеют фиксированный размер или множество типов и переменных размеров).
Также у нас были разные распределители для звуковых файлов / компонентов, чем для уровней и других игровых объектов в том же проекте. В других проектах распределители наследуются от внешних библиотек только для компонентов, управляемых этой библиотекой.
Оптимизация действительно зависит от ваших потребностей. Но обычно распределение выполняется до входа на игровую сцену, а затем память используется повторно. Некоторые игры могут обходиться без предоставления пользовательских распределителей. Но в экшен-играх, где ресурсы процессора, памяти и данных заложены в бюджет, вы не можете позволить себе терять время обработки при больших выделениях, вы не можете тратить память на фрагментацию и другие проблемы.
Что касается примеров, вы должны просто начать с просмотра игрового движка OGRE 3D, в котором есть несколько вариантов настройки распределителей памяти.
источник
Часто допускаемая ошибка заключается в написании собственных распределителей, чтобы вы могли лучше контролировать объем используемой памяти каждой системой и лучше видеть происходящее. Гораздо лучший способ добиться этого - использовать профилировщик памяти. Есть много профилировщиков памяти, мой пример - MemPro . Это абсолютно неинвазивный способ отслеживания всего использования памяти, и вы можете автоматически разбить его на подсистемы, используя фильтры подстановки callstack. В идеале лучше всего разделять выделение памяти и отслеживание памяти, они предъявляют совершенно другие требования.
Произвольное разделение вашей памяти на пулы часто может быть вредным, поскольку каждый пул будет иметь дополнительные издержки. Вы можете использовать гораздо больше памяти, чем вам нужно, даже не осознавая этого. Чтобы уменьшить потери, всегда лучше объединить все воедино, тогда недостаток распределяется по всей системе.
Единственными причинами использования пользовательских распределителей являются производительность процессора (в основном для когерентности кэша) и ограничение фрагментации. Прекрасным примером этого является система частиц. Вы хотите, чтобы все частицы были в памяти, и вы не хотите перетекать в основную память множеством недолговечных выделений. Еще один хороший пример разделения - язык сценариев.
Если вам нужен пример замены malloc общего назначения, вы можете взглянуть на мой распределитель VMem . Он был использован во многих поставляемых играх ААА. В нем есть методы, которые ограничивают фрагментацию и сохраняют объем памяти, что очень важно для консольных игр. Это также очень быстро в условиях высокой конкуренции. Мой сайт имеет обширную документацию по этим методам.
источник