Pull to refresh

Ускоряем загрузку карты в World of Tanks

Reading time 4 min
Views 185K

Заметил я как-то, что на моём компьютере карты в WoT загружаются очень долго — больше минуты. Заходишь, бывает, в бой, а он уже секунд 30 идёт. А иногда вообще обнаруживаешь свой танк уже в виде горящих обломков. Компьютер мой, конечно, старенький и давно просит апгрейда, но вначале можно попытаться сделать что-то программным путём.

Итак, первое дело — определить причину тормозов. Список подозреваемых, в принципе, не очень большой:
  • CPU
  • RAM
  • HDD
  • Сеть
  • Криворукость разработчиков игры
  • Барабашка
Начнём оперативно-розыскные мероприятия с очной ставки. Берём прекрасную утилиту Process Monitor от Sysinternals, запускаем, добавляем в фильтры мониторинг процесса worldoftanks.exe и — поехали. Стартуем игру, начинаем бой, ждём загрузки карты и смотрим на результаты мониторинга.

Как видно из скриншота, загрузка CPU, памяти и сети далеки от максимальных. А вот график загрузки HDD весьма неровный, есть пики и провалы. Давайте посмотрим детальнее. Жмём «Tools->File summary...». Бинго! Тут мы видим целую кучу операций ввода\вывода (70 602 штуки, если быть точным).

Общий объем читаемых по ходу загрузки данных составляет примерно 450 МБ, время работы файловых операций — более 50 сек. Значит именно файловые операции занимают большую часть времени загрузки карты. Оно и немудрено — в WoT хорошо проработанные карты, модели танков, всякие там дома\деревья\камни. 450 МБ читаемых данных выглядит адекватной ценой за всё это. Но как же мы можем ускорить время загрузки? Ведь все эти данные игре всё-равно нужно прочитать. Есть старый проверенный способ ускорения файловых операций — RAM диск. Но вот в чём беда — в лоб применить его не выйдет. Игра занимает 11 ГБ, а на моей машине всего 4 ГБ ОЗУ. То есть даже создав RAM диск размером 11 ГБ и поместив на него всю игру, я не обману законы физики и операционную систему — диск может и создастся, но данные на нём будут свопится на всё тот же жесткий диск, от использования которого мы хотим уйти. Не вариант.

Что ж, копнём глубже — посмотрим, обращения к каким именно файлам занимает больше всего времени. Открываем вкладку «By folder» и видим следующую картину.

Большую часть ресурсов кушает обращение к файлам в папке %World_of_tanks%\res. Тут можно выделить следующие подпапки:
  • audio: 14.48 сек — папка занимает 200 МБ
  • content: 9.93 сек — папка занимает 844 МБ
  • spaces: 6.19 сек — папка занимает 419 МБ
  • vehicles: 8.60 сек — папка занимает 1.7 ГБ
Если бы мы могли поместить в память файлы из некоторых этих папок, то загрузка карты значительно бы ускорилась. Например поместив в ОЗУ файлы из папок audio и spaces, мы выиграем 21 секунду времени ценой 619 МБ ОЗУ — вполне неплохо. Но в лоб этого сделать не выйдет — как же игре объяснишь, что часть её ресурсов лежит тут, а часть — там? В этом месте я уже хотел удариться в жёсткий хардкор в духе Harkonnen'a:
  1. Загружаем нужные файлы в память
  2. С помощью какого-нибудь Microsoft Detours или ApiHijack вешаем хуки на функции CreateFile, ReadFile (и может что-то еще) в процессе Worldoftanks.exe.
  3. В хуках определяем, какой именно файл пытается читать WoT. Если один из наших — даём ему данные из памяти, если левый — перекидываем вызов на настоящие функции файлового ввода\вывода.

Но, к сожалению, не сложилось — мне в голову пришла идея, которая позволила сделать всё в разы проще и этим всё испортила :). Идея состояла в том, что, дескать, как бы классно в этом месте было бы быть пользователем *nix-систем, где есть прекрасная команда mount, позволяющая примонтировать что угодно куда угодно. В Windows такого нет… Или есть? На периферии сознания витали какие-то смутные воспоминания и я полез в голову и Гугл за информацией (когда уже ребята из Гугла в конце-концов сделают поиск в моей голове — совсем обленились что-то!). Итак, вот что мы имеем под Windows:

  • subst — делает ровно противоположное тому, что нам надо. Позволяет создать новый виртуальный диск, корнем которого будет являться заданная папка. А нам нужно наоборот — связать существующий диск с «виртуальной» папкой.
  • Cпособ, описанный в Microsoft KB 307889 — на первый взгляд делает то, что нам нужно. Позволяет для файловой системы NTFS создать связь между некоторой папкой и корнем диска. Прекрасная штука, но, к сожалению, не заработала с моим RAM-drive (даже когда я отформатировал его в NTFS).
  • Ну и наконец я решил поискать там, откуда подобный поиск следовало начинать — в списке утилит от Sysinternals. И, конечно же, там нашлось то, что мне было нужно. Утилитка Junction позволяет примонтировать к определенной папке любой путь в нашей файловой системе (есть еще одна похожая — linkd).
Таким образом, окончательный алгоритм выглядит так:
  1. Берём любой RAM-drive (например из вот-этого списка). Я взял вот этот.
  2. Думаем, сколько ОЗУ мы можем выделить под кеширование.
  3. Переписываем папки с ресурсами игры на RAM-drive (оригинальные папки переименовываем — они нам еще понадобятся).
  4. С помощью Junction монтируем папки на Ramdrive в папку ресурсов игры. Как-то так:
    «junction D:\Games\World_of_Tanks\res\audio r:\audio»
  5. Запускаем игру и наслаждаемся.
К стати, все эти пункты можно реализовать в одном батнике, а во втором — откат всего обратно.

Конечно, в этом всём деле важно не переборщить, чтобы объем файлов на RAM-drive не стал столь большим, что ОС решит задействовать своппинг — тогда вся идея летит к чертям. Но вот что вышло у меня:

Время обращения к файлам в папках на RAM-drive упало практически до нуля, карта стала грузиться намного быстрее, я стал появляться часто еще до начала предстартового отсчёта, успевать перекинуться парой фраз с союзниками перед началом боя. В общем, чего хотел — добился. Жаль всё-же что не довелось глубже покопаться в недрах игры и заюзать хуки — но зато мой способ не нарушает лицензионного соглашения WoT, что тоже немаловажно.
Tags:
Hubs:
+114
Comments 83
Comments Comments 83

Articles