Поделиться через


Основные проблемы с заголовками Windows

Группа Microsoft Windows Gaming and Graphics Technologies Developer Relations выполняет анализ производительности для многих игр Windows каждый год. Во время этих сеансов мы получаем практический опыт, чтобы связаться с отзывами разработчиков и запросами, которые мы получаем ежедневно. Иногда мы помогаем отследить таинственный сбой или другие проблемы в названии, что дает нам более подробное представление о проблемах, с которыми сталкиваются разработчики.

В этой статье рассматриваются многие распространенные проблемы, с которыми мы сталкивались в играх для пк текущего поколения.

Производительность CPU-Limited

Подавляющее большинство игр ограничено производительностью ЦП в системах с высокопроизводительными графическими процессорами (GPU). Иногда это связано с плохим использованием пакетной обработки для отрисовки отправок, но, как правило, это происходит из-за того, что другие игровые системы потребляют большую часть доступных циклов ЦП. В некоторых случаях, когда мы рассматривали GPU в качестве ограничения, причиной является очень высокая скорость заполнения или потребность в пиксельных шейдерах в параметрах с высоким разрешением или низкая производительность вершинного шейдера видео карта.

Так как большинство игр ограничены ЦП, наибольшую производительность выигрывает оптимизация игровых систем с интенсивным использованием ЦП. Как правило, системы искусственного интеллекта или физики и связанная с ними логика обнаружения конфликтов являются основными потребителями циклов ЦП в приложениях Microsoft Direct3D. Любая работа по улучшению этих систем может повысить общую производительность игры.

Плохое пакетное управление

Для достижения хорошего параллелизма с GPU требуется, чтобы пакеты рисования содержали достаточно геометрии( а шейдеры имели правильную сложность), чтобы видео карта занято, не используя столько пакетов, что буфер команд переполнен. На оборудовании текущего поколения рекомендуется использовать примерно 300 или меньше пакетов отправки отрисовки на кадр (меньше на ЦП с более низкой производительностью), чтобы обработка буфера команд драйвером не стала узким местом производительности. Некоторые другие вызовы состояния API и сочетания драйверов могут привести к дорогостоящей обработке ЦП (например, компиляция драйвера шейдеров), поэтому мы настоятельно рекомендуем проводить регулярный анализ производительности.

Чрезмерное копирование памяти

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

Чрезмерное использование отправки динамического рисования

Современное видеоустройство хорошо работает при работе со статическими данными. Высокопроизводительные адаптеры часто имеют очень большой объем видеопамяти, но эта память не может эффективно использоваться динамическими данными.

Хотя для динамического содержимого можно реализовать достаточно эффективные шаблоны использования динамических буферов вершин или буферов индексов, многие заголовки слишком часто применяют эту идиому для того, что в противном случае является статическим содержимым. Чаще всего это можно увидеть с деревьями секционирования двоичных пространств (BSP) и системами на основе портала, которые хранят геометрию в структуре данных, которая не сопоставляется с оборудованием и должна быть обработана в буферы для каждого кадра. Размещение как можно большего объема содержимого в статических ресурсах может значительно снизить затраты на пропускную способность при передаче данных в видео карта, лучше использовать встроенную виртуальную память и снизить нагрузку на ЦП и кэш, связанные с обработкой этого содержимого.

Высокая нагрузка на обработку файлов

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

Затраты на открытие файла обычно гораздо выше, чем ожидают разработчики. Благодаря широко используемым сканерам вирусов по запросу и дополнительным функциональным возможностям NTFS открытие файла является довольно дорогостоящей операцией. Поэтому открытие нескольких файлов одновременно или повторное открытие и закрытие одного и того же файла является плохим методом управления файлами. Некоторые игры пытались снизить эти затраты на производительность, проверив наличие файла перед его открытием. Реальность такова, что проверка существования файла в NTFS требует открытия файла, поэтому тестирование перед открытием приводит к двойной оплате.

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

Дополнительную производительность можно получить в файловой системе следующим образом:

  • Правильное использование указаний файловой системы FILE_FLAG_RANDOM_ACCESS и FILE_FLAG_SEQUENTIAL_SCAN
  • Изменение размера буферов, чтобы избежать большого количества вызовов API для чтения и записи ОС
  • Асинхронный доступ к файлам
  • Загрузка потоков в фоновом режиме

Мы также настоятельно рекомендуем преобразовывать данные в автономном режиме (во время сборки или установки), а не полагаться на преобразование при первом запуске игры, так как это накладывает значительный налог на производительность для каждого пользователя.

Медленная и разочаровывающая установка

Еще одна распространенная проблема, которую мы видели, — это очень длительное время установки, необходимое для многих современных игр для ПК. Установщики много раз запрашивают пользователя, иногда просто говоря пользователю, например: "Не требуется устанавливать DirectX". Как правило, эти установщики требуют, чтобы пользователь нажимал кнопку Далее или ОК много раз, прежде чем начнется установка игры. Как только он начнется, мы видели, что некоторые названия занимают час или более, прежде чем пользователь получит возможность играть в игру. Мы считаем, что первый час игрового опыта не должен быть установкой.

Мы рекомендуем использовать ряд подходов к работе с установкой. Во-первых, оставьте подсказки простыми и сведите к минимуму. Во-вторых, создайте свои игровые данные таким образом, чтобы некоторые или все файлы данных можно было по возможности использовать непосредственно с диска распространения — современные DVD-диски имеют очень высокую пропускную способность. В-третьих, рассмотрите возможность реализации установки по запросу в своих названиях, чтобы сократить или исключить процесс установки и позволить пользователям как можно быстрее войти в игру. (Дополнительные сведения об установке по запросу см. в разделе Установка по запросу для игр.)

Дополнительные рекомендации по установке игр см. в разделе Упрощение установки игр.

Отсутствие учета физической памяти

Из-за широкой изменчивости оборудования пк на рынке названия обычно используют нерегламентированные тесты конфигурации для выбора параметров по умолчанию для уровня графической детализации. Некоторые из названий, которые мы видели, используют размер видеопамяти в этих тестах, но не могут сопоставить его с размером физической памяти. Чтобы справиться с ситуациями потери устройств, большая часть видеопамяти (как локальная виртуальная память на карта, так и нелоконная диафрагма памяти AGP) должна поддерживаться физической памятью, либо с помощью управляемых ресурсов, либо пользовательских структур данных. Некоторые высокопроизводительные видеоадаптеры имеют размеры виртуальной памяти, соперничающие с объемом памяти ЦП низкого уровня. В ситуациях, когда система имеет ограниченный объем физической памяти по сравнению с карта видео, большая часть этой виртуальной памяти не может быть эффективно использована, и необходимо настроить более низкие параметры детализации.

Over-Reliance при преобразовании частоты выборки звука Real-Time

Еще один распространенный источник сгорания цикла ЦП, который мы видели, возникает, когда звуковая система требуется для преобразования скорости воспроизведения во время микширования в аппаратный буфер. В драйверах windows Driver Model (WDM) формат аппаратного буфера не находится под прямым контролем приложения, так как это ресурс уровня ядра; Вместо этого формат выбирается на основе формата самого высокого качества из всех источников и возможностей оборудования. По умолчанию Windows XP использует для этого процесса высококачественное преобразование частоты выборки, и если для большинства звуковых примеров требуется преобразование скорости, будет использована значительная часть циклов ЦП.

Рекомендуется создать все буферы DirectSound с одинаковой частотой выборки. Если вы используете какие-либо функции Microsoft Win32 waveOut , вы также должны использовать согласованную частоту выборки с этими функциями. При использовании драйверов WDM все буферы будут смешиваться ядром, и если в некоторых из них используется более высокая частота выборки, частота выборки всех остальных будет преобразована в соответствие. Обратите внимание, что это подразумевает использование одинаковой скорости воспроизведения для всех примеров звука, включая любые буферы распаковки потокового звука. Установка частоты основного буфера не оказывает никакого влияния, если только вы не нацелены на Windows 98 или Windows Millennium Edition.

Примечание

В Windows Vista и более поздних версиях операционной системы DirectSound и waveOut используют API сеанса звука Windows (WASAPI) для всех аудиовыходов.

 

Фрагментирование виртуальной памяти

Мы сталкивались с рядом недавних проблем, связанных с 32-разрядным ограничением на объем памяти процесса. Хотя 2 ГБ виртуального адресного пространства для процессов в пользовательском режиме исторически было более чем достаточным, увеличение использования больших файлов, сопоставленных с памятью, пользовательских распределителей памяти и увеличение размера виртуальной памяти (которая должна быть сопоставлена с пространством процесса) стали приводить к сбою выделения пространства виртуальной памяти. Некоторые сторонние библиотеки DLL используют расположения с фиксированным запуском в середине виртуального адресного пространства, что приводит к фрагментации, что приводит к сбою выделения.

Эти проблемы чаще всего возникают, когда игра использует пользовательскую схему выделения памяти, которая пытается выделить большой непрерывный кусок виртуальной памяти. Мы рекомендуем написать распределители таким образом, чтобы они запрашивали более разумный размер частей виртуального адресного пространства по мере необходимости. Например, запрос 64 или 256 МБ за раз, но не 1 ГБ. Однако следует проявлять осторожность, чтобы не вызвать дальнейшую фрагментацию. Появление 64-разрядных операционных систем и оборудования в значительной степени поможет этим проблемам в будущем, но необходимо проявлять осторожность в отношении 32-разрядных систем текущего поколения.

Управление Word элемента управления Floating-Point

В качестве помощи для отладки некоторые разработчики включали исключения для единицы С плавающей запятой (FPU) с помощью манипуляций с контрольным словом с плавающей запятой. Это весьма проблематично и, скорее всего, приведет к сбою процесса. Так же, как соглашение о вызовах требует сохранения регистра ebx, большая часть системы предполагает, что FPU находится в состоянии по умолчанию, даст разумные результаты и не создаст исключений. Драйверы и другие системные компоненты часто вычисляют результаты на основе предположения, что стандартные значения ошибок будут отображаться в регистрах для плохих условий, но если исключения включены, они будут необработанными и приводят к сбоям.

Direct3D установит единицу с плавающей запятой с одной точностью и округлением к ближайшему в рамках инициализации вызывающего потока, если только не используется флаг D3DCREATE_FPU_PRESERVE. В этом случае управляющее слово с плавающей запятой не будет тронуто. Так как контрольное слово является параметром для каждого потока, обеспечение того, чтобы все потоки приложения были настроены в режиме одиночной точности, может оптимизировать производительность. Помните, что вызов _control87 недопустим для 64-машинного кода, в котором используется исключительно SSE, и это очень дорого для архитектуры на основе PowerPC ЦП Xbox 360.

Примечание

При изменении контрольного слова используйте _controlfp_s и помните, что для платформ x64 нельзя изменить точность с плавающей запятой с помощью контрольного слова.

 

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

Необязательная установка среды выполнения DirectX

В некоторых играх пользователь запрашивает, следует ли установить DirectX. Это может привести к проблемам, если пользователь предполагает, что в системе установлена последняя версия распространяемого компонента DirectX и пропускает установку, а затем установка успешно продолжится. Если для игры требуется определенная версия D3DX или другие обновленные функции, которые не были установлены, то игра не будет работать, и пользователь будет очень разочарован.

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

Автоматическую установку DirectX можно выполнить, выполнив следующую команду из пакета установки: dxsetup.exe /silent

Кроме того, фактический размер распространяемой папки можно настроить так, чтобы она включала только те файлы кабинетов (.cab), которые действительно необходимы для целевых платформ и использования игры.

Примечание

Прежде чем использовать dxsetup, прочтите статью Не так прямая настройка.

 

Чрезмерное использование синхронизации потоков

При профилировании игр основные горячие точки часто связаны с вводом и выходом из критически важных разделов. С распространением многоядерных ЦП использование многопоточности в играх резко возросло, и многие реализации полагаются на интенсивное использование синхронизации потоков. Время ЦП на выполнение критического раздела даже без каких-либо состязаний является довольно значительным, а все другие формы синхронизации потоков еще дороже. Таким образом, необходимо соблюдать осторожность, чтобы свести к минимуму использование этих примитивов.

Распространенным источником чрезмерной синхронизации в играх является использование D3DCREATE_MULTITHREADED. Этот флаг, делая Direct3D потокобезопасным для отрисовки из нескольких потоков, использует очень консервативный подход, что приводит к большим затратам на синхронизацию. Игры должны избегать этого флага. Вместо этого создайте архитектуру подсистемы таким образом, чтобы все взаимодействие с Direct3D осуществляется из одного потока, а любая связь между потоками обрабатывалась напрямую. Дополнительные сведения о разработке многопоточных игр см. в статье Написание кода для нескольких ядер на Xbox 360 и Microsoft Windows.

Использование RDTSC

Не рекомендуется использовать инструкции x86 RDTSC . RDTSC не может правильно вычислить время в некоторых схемах управления питанием, которые динамически изменяют частоту ЦП, и на многих многоядерных ЦП, для которых счетчик циклов не синхронизируется между ядрами. Вместо этого в играх следует использовать API QueryPerformanceCounter . Дополнительные сведения о проблемах с RDTSC и реализации времени с высоким разрешением с помощью QueryPerformanceCounter см. в статье Game Timing и многоядерные процессоры.