Выжимаем больше из выделенных игровых серверов оптимизацией сетевого кода

Ожидания: больше толку за меньшие деньги

Игровое сообщество постоянно меняется. По мере появления новых технологий — DSL, оптоволокно и кабельный модем — и постоянного облегчения возможности домашним пользователям подключить высокоскоростной интернет, расёт и число казуальных и хардкорных онлайн-игроков — и всё они хотят играть больше, лучше, быстрее! А их личные мера хорошей связи — это пинг. Остается шаблон восприятия: «хороший пинг» означает «хорошая игра». Хостеры игровых серверов, издателей игр и отдельные лица, которые которые хостят игровые серверы, стараются предоставить хорошее качество связи. Арендованный сервер Half-Life Counter-Strike с T1-соединением для 32 игроков, возможно, мог стоить пару лет назад $150 в месяц. Теперь его можно можно получить за $25. Так как же компании, хостящие игровые серверы, должны получать прибыль?

Один из способов, которым хостинг-компании добиваются прибыли — увеличение производительности оборудования. Новые поколения процессоров и последние четырёхъядерные машины, работающе под управлением серверерных версия ОС Windows или Linux, имеют возможность разместить сразу несколько игровых движков на одной системе.

Еще один способ окупать затраты на хостинг игр — предоставление «самоуправляемых» игровых серверов. Такие панели управления сервером хостинг-компании предлагают пользователям за дополнительную оплату: от $5 до тысячи в месяц за счет снижения административных расходов пользователей в виде настраиваемого веб-хостинга утилиты удалённого администрирования игровых серверов. Эти инструменты позволяют заняться самостоятельным обслуживанием своих арендованных серверов даже технически неграмотным клиентам, будь то загрузка новых карт игры, либо остановка и запуск различных конфигураций игрового сервера.

Ужимаем сервер: как получить больше

Итак, сеть и серверное оборудование на месте. Есть так много клиентов, как только может позволить инфраструктура. Что еще можно сделать для улучшения производительности, и, возможно, мощности, без добавления дополнительного оборудования? Один из оставшихся подходов — заставить серверное программное обеспечение работать лучше.

Это означает работу над «тюнингом» серверных бинарников для улучшения их работы. Это предполагает, конечно, что у вас есть доступ к исходному коду игрового сервера. Если вы — разработчик игры или часть сообщества мода своей любиой игры, у вас, возможно, уже есть доступ к исходникам. Если вы достаточно большой заказчик игры (например, владелец большого игрового клуба) или способствуете большим продажам игры (например, держите много серверов с последним релизом игры X), у вас есть шанс договориться о доступе к исходникам или убедить разработчика/издателя произвести некоторые улучшения производительности кода от вашего имени.

Если вы имеете доступ к исходным кодом, вы можете предпринять несколько шагов по оптимизации, в том числе применить процессоро-зависимую общую оптимизацию и оптимизацию, ориентированную на определенный тип процессора, в том числе 64-битной архитектуры.

Основная оптимизация

Хорошим первым шагом к наращиванию производительности вашего сервера будет скомпилировать его эффективным оптимизирующим компилятором. Одним из вариантов является Intel C/C++ Compiler, доступнsq как в Linux, так и в Windows. Если сервер написан под Windows, разработчики программного обеспечения могут уже использовать Microsoft DevStudio IDE с встроенным в него Intel C/C++ компилятором для создания проектов. Если сервер написан под Linux, пользователь может выбрать для использования Eclipse Software Development CDT или хороший старомодный редактор командной строки и «make».

С чего начать? Для тренировки был выбран солидный движок игры: R1Q2 Ричарда Стэнвея. Это растянутая и расширенная версия движка Quake 2, который был опубликован как Open Source ID Software в 2001 году. Древний код? Да, но многие программисты игр сточили зубы на развитии модов Q2. Это достаточной известный движок и хорошая точка отсчета. R1Q2 Рича включил в себя код из мода LOX для Q2, модом «экстремальное оружие» Дэвида С. Мартина и его друзей, и дорабатывался Джефф Geoy и другими. Мод LOX является хорошим примером исполнения сложного кода, способного генерировать огромное число событий при всего одном игроке, который определённым выбором оружия и комбинацией действий может поставить на колени мощный сервер.

Для этого примера целевая платформа — сервера Linux, и по умолчанию выбор среди хостинговых компаний ложится на те, которые предлагают Linux сервера. Тестовый сервер управляется ванильной ОС Red Hat Enterprise Linux 3 (Taroon Update 4), работающей на 3,7 GHz Pentium 4 с 1 гигабайтом оперативной памяти, со стандартным Serial ATA жестким диском. Обратите внимание, что все шаги, обсуждаемые здесь, в том числе методы оптимизации и особенности компилятора, точно так же доступны под Windows.

Шаг первый:

Получить код. Распаковываем код и исполняем стандартную компиляцию gcc, используя флаг оптимизации —O2 с прилагающимися Makefile`ами, которые будут генерировать исполняемые файлы, как от них и ожидалось. Пара клиентских машин, работающих в изолированной сети без проблем со связью и пингом, варьирующимся от 15 до 35 мс. Поскольку этот код более-менее прилизан, предупреждения компилятора будут минимальными.

Шаг второй:

Произведём калибровочное тестирование. В данном случае две клиентских машины были подключены к серверу, запущенному стандартными версиями бинарных файлов. Их средние пинги были записаны, как и их пинг, когда сервер был нагружен. В данном случае принимающие участие в стресс-тесте игроки на обоих машинах запускали 4 напалмовых гранаты в секунду из фиксированного положения на карте сервера по умолчанию, создавая в игре не менее 128 взрывов в секунду. Клиент зримо «заморозил» — поведение, типичное в состоянии загрузки сервера, также наблюдались частые варнинги «RATEDROP», выдаваемые сервером, когда наблюдается значительное падение скорости обмена данными между клиентом и сервером.

Шаг третий:

Берём компилятор Intel. Пакет Intel C/C++ Compiler доступен для скачивания как демо, а так же в виде академических, некоммерческих и коммерческих лицензий. Программное обеспечение устанавливается на почти все основные дистрибутивы Linux, в том числе не поддерживающие RPM.

Шаг четвертый:

Обновляем Makefiles для включения параметров оптимизации. В этом случае, это означало изменение «CC = GCC» до «CC = icc». R1Q2 Makefile не требует изменения зависимостей или LDFLAGS. Makefile LOX требуется незначительное изменение настройки LDFLAGS для указания новой директории размещения библиотек для нескольких ключевых строковых функций.

Для общей оптимизации CFLAGS компилятора были изменен: мы добавили флаг оптимизации -02. Это наиболее часто рекомендуемый вариант, выполняющий много оптимизаций для увеличения скорости работы без существенного влияния на размер кода, включая, но не ограничиваясь:

* Встраивание (inline-функции)
* Прямая подстановка
* Объявление констант
* Ликвидация мертвых статических функций, кода и данных
* Хвостовая рекурсия
* Частичная ликвидация избыточности

Единственное, что стало видно сразу во время начальной компиляции с помощью компилятора Intel — это то, что количество предупреждений увеличилось с 4 до 62. Большинство предупреждений касались вопроса проверки типов. Некоторые из них заслуживают дальнейшего исследования. В данном случаев коде были необходимы лишь незначительные изменения. Вновь скомпилированные бинарники были протестированы и результаты записаны.

Для следующего раунда оптимизации флаги CFLAGS были изменены с -02 до -03. Этот вариант, в соответствии с документацией, подразумевает «более агрессивную оптимизацию, такую как предварительная загрузка, скалярные замены, и петли и преобразование доступа к памяти». -03 включает в себя все особенности оптимизации -02, а также развертывание цикла, репликацию кода по ликвидации ответвлений, и заполнение некоторых двумерных массивов, чтобы улучшить использование кеша. Опять же, ново-собранные файлы были протестированы и результаты были записаны.

В третьем раунде двоичные файлы были построены с добавлением флагов -aXN. Эти флаги позволяют производить процессор-ориентированную оптимизацию, в данном случае специально для Intel Pentium 4 и совместимых чипов. И снова новые бинарники были протестированы.

Заключительный раунд оптимизации флагов компилятора состоял из замены -axN на -axP. Эта опция оптимизирует бинарники для поддержки Intel Pentium 4 с Streaming SIMD Extensions 3 (SSE3). Результаты снова были проверены.

Результаты тестирования

Двух клиентских машины, используемые для тестирования:

* Машина 1 — 2,9 GHz Pentium 4 с 512 Мбайт оперативной памяти, запущен R1Q2 Quake 2 клиент в режиме OpenGL при разрешении 1024х768 пикселей
* Машина 2 — 1,3 GHz Celeron с 512 Мб оперативной памяти, с запущенной версией 3.20 клиента ID Software в режиме программного рендеринга при разрешении 1024х768 пикселей

Вот краткое изложение результатов:

Выводы оптимизации компиляции

Полученные результаты показывают, что нет существенной разницы между пингом при копилировании GCC -O2 и ICC -O2. Кроме того, интенсивность появления предупреждений о потере кадров и время восстановления после состояния стресса совсем-совсем незначительно лучше с компилятором ICC. Результаты выглядят гораздо более значительными при сборке с уровнем оптимизации -O3 и ещё более внушительными, когда добавляем процессоро-ориентированную оптимизацию -axN и -axP.

Приведённые тесты не являются идеальной моделью поведения в динамичной среде, где игроки будут подключаться из всей компании или по всему миру. Но они служат для демонстрации возможностей для улучшения.

Ясно, что пинг не единственный показатель производительности. Хотя усовершенствования, внесенные в тестовые программы, несколько улучшили пинг, основное их воздействие было замечен в способности сервера поддержания плавного процесса игры и в восстановлении его после периодов интенсивной деятельности. Это и есть то, о чём эта статья.

Дополнительные меры по улучшению бинарников

Показанных выше результатов может быть кому-то достаточно. Если всё еще требуется ещё большее увеличение производительности, есть ряд дополнительных шагов, которые могут быть предприняты. Хотя эти шаги выходят за рамки этой статьи, они заслуживают упоминания в качестве областей будущих исследований, особенно для разработчиков новых игр.

Одним из таких шагов является применение профилировщика чтобы определить, где находятся узкие места программы игрового сервера. Такие инструменты, как VTune от Intel Performance Analyzer можно использовать, чтобы найти источники медлительности программы, определить ключевые алгоритмы, которые могут быть улучшены, и указать на другие возможности оптимизировать поведение программы.

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

Другие способы для улучшения производительности сервера

Есть, конечно, фундаментальные вещи, которые администратор игрового сервера может предпринять, чтобы гарантировать, что игра на хостинге оптимально настроена и наилучшим образом осуществляет все действия, которые в неё заложили программисты. Несколько ключевых параметров конфигурации сервера, существенно влияющих общую производительность, могут быть регулируемыми для каждой конкретной игры. Хотя они отличаться от игры к игре, они могут включать:

* Практические предел игроков (т.е. не позволять администратору сервера настроить это число выше заложенного лимита. Ограничение количества пакетов, которые превышают способность игрового движка по их доставке)
* Жесткий потолок пинга до игроков (т.е. игроков с пингом больше определенного предела не допускать, в целях защиты качества игры для остальных)
* Ограниченная пропускная способность или отключение загрузки карт, моделей, аудио и другого необязательного «level-specific» содержания.
* Ограниченная пропускная способность или отключение загрузки «player-specific» содержанием, таким как «скины» и «спреи, если такие функции поддерживаются игрой.
* Лимит производительности FPS (может быть выражен как максимальное количество игровых обновлений в секунду)

Последний вариант: вы всегда можете изменить игру. Новый подход к улучшению производительность сервера, принятой Ричардом Стэнвеем в его моде R1Q2, включает в себя вывод загрузки карт / текстур / ауди на сервер HTTP. Это означает, что функция закачки карты опционально может быть переложена на отдельные системы, пожалуй, даже на отдельные подсети для минимизации воздействия на сеть сервера, с софтом, работающим на более высокой скорости передачи данных, чем существующие TCP игры могут поддержать.