Производительность GameMaker Studio

Материал из Вики по GameMaker
(перенаправлено с «Производительность GameMaker»)
Перейти к: навигация, поиск

Как известно, чтобы оптимизировать игру, нужно знать, что именно её тормозит. Для этого есть профайлер, который с большой детализацией покажет, какие именно функции работают медленнее всего - именно их и надо оптимизировать. Выполнять оптимизацию до того, как функция полностью делает свою работу - зло. Это влечёт за собой постоянные переписывания кода по мере роста функции, неведомые баги, и прочие неприятности. Но и заранее знать у чего какая производительность тоже очень полезно - можно конструировать код зная наперёд, что будет тормозить, а что - не будет.

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

Содержание

[править] Общее

  • Глобальное ограничение на объем потребляемой памяти - 2 гигабайт
  • Пустой исполняемый файл весит 14 мегабайт (Windows)
  • Игровая логика (кнопки и код GML) работает в один тред, и может нагрузить только одно ядро
    • Всего в игре 12 тредов, они могут занимать другие ядра

[править] Массивы

  • Массивы занимают по 16 байт памяти на 1 ячейку (кроме текста)
    • Неинициализированные ячейки ничего не занимают, даже если массив огромного размера
      • Чтение неинициализированной ячейки не считается за инициализацию и всегда возвращает 0
  • Максимальный размер массива - 32767 ячеек, для двухмерного - 32767 х 32767
  • Двумерные массивы представляют собой jagged array с главной осью Х, каждый столбец нужно инициализировать в отдельности, иначе при обращении к неинициализированному столбцу игра может вывалиться с ошибкой выхода за границы массива (GMS 1.4.1474).
    • Каждый столбец двумерного массива может иметь свой собственный размер
  • Инициализация массива в обратном порядке в 20 раз быстрее, чем в прямом порядке
    • Просто установка верхнего значения массива не считается за полную инициализацию, проходить по всем ячейкам в первый раз нужно в обратном порядке в любом случае
  • Одномерный массив на 40% медленнее, чем обычные переменные
  • Двухмерный массив медленнее одномерного в два раза (на 260% медленнее обычных переменных)
  • Переменные массивов не содержат сам массив, а только ссылку на него. Если один и тот же массив присвоить нескольким переменным, то все они будут указывать на ту область памяти, где находится массив - работа над массивом через любую из этих переменных будет модифицировать исходный массив
    • В ячейки массива можно указывать другие массивы - будет записана ссылка на массив. Адресовать под-массивы напрямую нельзя, нужно сначала извлечь под-массив в переменную
    • Если переменной массива присвоить другое значение, массив будет мгновенно удалён из памяти. Пока хоть одна переменная указывает на массив, он не будет удалён из памяти.
  • Массивы передаются в функцию по ссылке - аналогично с присвоеним массива другой переменной
    • Если изменить массив внутри функции - перед этим он полностью скопируется в память функции и исходный массив не будет затронут
      • Можно изменить исходный массив по ссылке используя аксессор "@"
      • Скорость копирования массива в функцию в 20 раз превышает скорость его инициализации через цикл в обратном порядке
      • Если из функции вернуть модифицированный массив, то он останется в памяти параллельно с исходным массивом, а не будет удалён как только функция закончит выполняться

[править] Структуры данных

[править] ds_list

  • Каждая ячейка занимает 16 байт (кроме текста)
  • Лист на 30% медленнее одномерного массива

[править] ds_grid

  • Грид не имеет ограничений по размеру
  • Каждая ячейка занимает 16 байт (кроме текста)
  • Чтение из грида незначительно быстрее двухмерного массива (5%)
  • Запись в грид незначительно медленнее двухмерного массива (3%)

[править] ds_map

  • Каждая ячейка мапа занимает 88 байт (кроме текста)
    • Текстовые ключи - дополнительно 32 байта и более (в зависимости от длины)
  • Мап в 4.3 раза медленнее одномерного массива
    • Если при каждом обращении нужно искать значение по ключу путём перебора, мап выгоднее чем массив если в нём больше 3-х элементов
    • Скорость добавления новых записей в мап быстро проседает по мере его роста
  • Запись в мап на 10% медленнее, чем чтение
    • Запись в мап через аксессор на 15% медленнее, чем через функцию

[править] Функции

[править] Рендеринг

  • Любые операции, разрывающие "цепь" данных, отправляемых на GPU, ударяют по производительности
    • Отрисовка фигур, примитивов, кругов, линий, стрелок, квадратов и т.п.
    • Переключение шейдера
    • Переключение текущей текстуры
      • GameMaker заталкивает все спрайты, бекграунды и шрифты в большие атласы, чтобы снизить частоту переключения текстур
      • Отрисовку нужно оптимизировать так, чтобы минимизировать переключения атласа - рисовать спрайты в таком порядке, чтобы не приходилось часто переключать атласы, и затолкать побольше спрайтов, рисуемых подряд, в один атлас
      • Атласы можно использовать и в 3д, но составлять их нужно будет вручную, равно как и лепить на 3д-модели
Вырожденные треугольники.
  • В шейдерах снижают производительность наличие команды discard, сэмплинг через координату текстуры изменённую внутри шейдера (в современных устройствах может не играть роли)
    • Сильно снижают производительность ветвления (if/else), циклы (for/while), инициализируемые внутри шейдера массивы (их нужно передавать извне через uniform)
    • Модели, рисуемые через trianglestrip отрисовываются быстрее, чем через trianglelist и чем отдельные модели, так как на большинство треугольников приходится всего один вертекс и соответственно один обсчёт вертекса в шейдере. Чтобы сделать "разрыв" в ленте треугольников, нужно использовать вырожденные треугольники (degenerate triangles) - на краю ленты поставить дополнительный вертекс в той же точке, следующую ленту начать с двух одинаковых точек. Таким способом также можно объединять несколько моделей в цельную модель.
Персональные инструменты
Пространства имён

Варианты
Действия
Навигация
Инструменты