ИГРА БЕЗ РАЗРЫВОВ
Игры под PC. Спайки, лаги, подтормаживания. В контракте описаны, спорить сложно.
Но что делать если НЕ БЫЛО НИ ЕДИНОГО РАЗРЫВА? На выходных возникла идея потестировать стримминг на PC. В результате усилий родился вот этот уродец http://ifolder.ru/6963373
Есть плоский файл, объемом на гигабайт. Камера движется в плоскости XY, в определенной области видимости создаются текстуры ( POOL_MANAGED, честная функция CreateTexture ). Для текстуры создается файловый запрос со случайного смещения. Файл открывается с флагами FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED. Я немного напомню – первый флажочек отключает буфферизацию IO на уровне файловой системы, второй флажочек разрешает асинхронные операции.
Асинхронное чтение в Windows работает очень просто – ты даешь внутрь указатель на область куда читать, размер и указатель на OVERLAPPED структурку. После начала операции в структуре взводится флажочек IO_PENDING, после завершения чтения этот флажок будет снят.
Утверждается, что асинхронный вызов ReadFile представляет удобные средства абстракции для DMA операций с жестким диском. Запросы могут складываться в очередь, выполняться в оптимизированном порядке, так далее. Цена асинхронного чтения без буфферизации – все смещения и размеры должны быть не абы какими, а кратными грануляции жесткого диска ( обычно степень двойки, до 4 килобайт ).
Итак, технология ниппель. Текстура создается в managed пуле с помощью CreateTexture. Выделяется с помощью VirtualAlloc буфер с правильным выравниванием, туда мы направим чтение со случайного смещения в ресурсном файле. Когда чтение будет завершено – мы зальем данные в текстуру. Могли бы в ReadFile передать и прямо Lock от текстуры, да только этот буфер с неправильным выравниванием.
Здравствуй, тройное копирование! Впрочем, в реальности все грамотные пацаны используют всякие LZO и zlibы, так что копирование сразу после дисковых операций можно заменить на декомпрессию.
Итак, написал я программку, 70 мегабайт активная область с текстурами. В уме держим 70 мегабайт на managed зеркало и 70 мегабайт на эти самые области стримминга, выделенные с помощью VirtualAlloc. Всего 512 мегабайт памяти на одышливом ноуте, с трудом треть свободна.
И – все летает. Стабильные 6-7 мегабайт в секунду трафика с жесткого диска. Больше он выдать не может – когда камера останавливается, то еще 3-4 секунд текстуры догружаются. Никаких спайков. Никаких лагов. Никаких тормозов. НЕТ РАЗРЫВОВ.
Сразу возникает вопрос, почему в играх наблюдаются стабильные тормоза. И загрузка уровней по минуте. Для меня это – великое таинство.
Возникает ощущение что тормоза начинаются там, где кончается асинхронность. Надо отправлять сразу десять файловых запросов. Лучше сотню. Лучше тысячу. Никогда не ждать. Выполнился запрос – и слава Богу. Вы видели такой код в играх? Я – нет.
И у меня в проекте унылое говно, как и у всех. Куча синхронных чтений. Что асинхронное – то memory map от файла, который как-то там в соседнем потоке дрочится. Чуть менее унылое говно, но всего лишь чуть.
И тормозит именно этот код. А не мифическая “говноплатформа PC”. Не отмазывайтесь. В ваших проектах нет асинхронного стримминга, а есть куча синхронного говнокода.