ru en de fr pt

Производительность (Performance tests / Benchmark)

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

Железо: 

  • CPU 2 ядра (2300 Mhz на ядро)
  • 4Gb Ram
  • php 8.1 
  • SSD

Использование системных ресурсов от 11.2022

Процессор от 2 Ядер (чем больше тем быстрее смогут работать параллельно работающие программные сервера и производиться расчеты системой ):

  • Нагрузка в покое CPU ~ 0,05% (load average 1, 5 и 15 минут): 0.07, 0.02, 0.01
  • Нагрузка 100 ходящий ботов (эмуляция игроков) CPU 4.7% 0.1, 0.09, 0.02

RAM (оперативная память) от 4ГБ, нужна в целом для работы служб “железа” , сам программный сервер потребляет доп мощности по следующей формуле:

  • 1 Мб на запуска 1 экземпляра программного сервера ( 1 карта = 1 сервер )
  • ~ 1 Мб данных на загрузку информации о где на карте ходить можно, где препятствия
  • + ~ 0.005 Мб на каждого монстра, объект, игрока (в зависимости насколько много данных из базы будет браться)

Анализ минимальной скорости интернета, нагрузка 100 блуждающих объектов (постоянный поток пакетов с координатами) от 11.2022

При скорости интернета 0.22 Мбит/Сек при одновременной действии 100 мобов (игроков) на карте игровой пакеты будут отправляться и приходить в клиент игры и игра будет с начальными признаками freez’ов (критический порог когда она начнет тормозить) тк Ping (разница между отправкой пакета и получением назад данных) составляет 0.2 секунды (игра НЕ тормозит в 90% времени за счет технологий интерполяции позволяющая игрокам с медленным интернетом побыстрее выполнять действия в игре уравновешивая ситуацию)



Системные тесты 

Результаты замеров скорости различных технологий на сервере указаны как количество запросов в секунду (RPS)

Redis

get set 13 000 (используется асинхронный запрос на получение в работе сервера)
pub sub 40 000  (в рамках работы сервера ничего не пишется, только на других сервисах)

ZeroMQ

pub sub 300 000 (в асинхронном, неблокируемом режиме)

Shmop (раздельная память данных между процессами)

get 700 000

Libevent

остановка основного кода, вызов функций по таймеру, продолжение основного кода. работает на базе ticks в php добавляя некую асинхронность
300 000 вызовов 

Swoole

...

Opcache (кэшируемые данные в opcode)

get 50 000 000
- 30% скорости загрузки библиотек фреймворка при запуске процесса (в CLI не сильно актуально)

Обычная переменная

get 70 000 000

Semaphores / System V (раздельная память с неблокируемым и блокируемым доступом)

pub sub 30 000 (ограничение по длине 16 000 байт)
get с блокировками 40 000
get без блокировки 2 000 000

Workerman Websocket server

обработка запросов в секунду чисто сервером 1 700 000+  (согласно публичным тестам, на сервере разработки еще не проверялось )

Workerman http server

обработка запросов в секунду чисто сервером ~2 000 000 (согласно публичным тестам, на сервере разработки еще не проверялось ) с пропускной способностью канала превышающее это значение (так что она не является ограничивающим фактором)


PHP FPM

400 000 (при условии что настройки fpm max_children установлено в достаточном количестве и ядер процессора достаточно для поднятия соединений в нормальном режиме скорости и ни один потомок не ждет освобождения пула)
минимальное потребление CPU на процесс поднятый 0.7%

Стандартные функции php 

exec 30мс/вызов
pcntl_fork 1.2мс/вызов (только для поднятия сервера)
работы с mysql через php запись ~8мс (скачкообразно)
работа с mysql через php на запись асинхронно 1мс на непостоянных TCP (рассмотреть библиотеку Parallel , замерить скорости на отправку сообщений или использовать асинхронный TCP постоянного соединения)

Ниже среднее количество вызовов указанных функций в секунду (красным выделены текущие проблемные места):

microtime(true) 20 000 000
date("Y-m-d") 2 000 000
date("Y-m-d H:i:s") 1 000 000
localtime() 1 800 000
getdate() 1 100 000
(new \DateTime())->format("Y-m-d H:i:s:v") 700 000 
memory_get_usage() 70 000 000
asort 200 записей 100 000
get_object_vars 20 свойств 5 000 000
file_get_contents (он же fopen+fread ) 40 000
file_exists() 250 000
class_exists() 10 000 000 , на несуществующий  (полагаю проверяется наличие функций autoload ) 7 000 000
method_exists 20 000 000 на несуществующий (полагаю проверяется наличие в объекте метода __call) 11 000 000
$reflectionMethod = new ReflectionMethod(object $object, 'method_name') 8 000 000
$reflectionMethod->invoke()  10 000 000 (x4 быстрее если бы метод вызвался напрямую)
(new ReflectionMethod(...)) -> getParameters 40 000 000 (0 аргументов), далее: 10 000 000 (1 аргумент), 7 000 000 (2 аргумента)  и тп (в среднем на 1 аргумент падение скорости на 30% , +-5%)

new \ArrayIterator(...) - 500 000
implements \Iterator + его методы 1.000.000
array_intersect_key 5 000 000 (4 значения)
array_merge  5 000 000 (4 значения)
array_column 10.000.000 (1 значение, на 35% падение скорости за каждое доп значение)
ob_get_contents() + ob_clean() 10 000 000
ob_start() + ob_get_contents() +  ob_end_clean() 4 000 000

Сравнительный (одинаковые вводные)

json_encode() 1 800 000 vs serialize() 1 700 000
json_decode(... , true) 600 000 vs unserialize 700 000 (рассмотреть библиотеку Simdjson)
восстановление Объекта из строки new A( ... explode(',', $a)) 3 800 000
SeasLog::log 80 000 vs file_put_contents (..., date("Y-m-d H:i:s").'|'.getmypid().' ....') 5000 vs fopen('..', 'a') + fwrite 80 000 (используется для логов. принято решение писать логи через множественные TCP соединения асинхронно но с потерей порядка записи)

Тесты песочниц (обработчик кода добавляемый в админ панели пользователями)

Lua Sandbox (движок для компилируемого языка LUA)

call (closure отдает фиксированную строку )  70 000 (8 ядер + физ сервер дает x10 к скорости)
call (closure отдает вызов PHP функции сервера с параметрами  созданной с помощью registerLibrary число параметров значимо не влияет на скорость)  60 000 (8 ядер + физ сервер дает x10 к скорости)
callFunction (аналог call но взывает не closure, a именованную глобальную функцию lua) - аналогично параметрам выше

Заметки:
  • данной технологии PHP и LUA не имеют общего хранилища и все данные передаются в виде сообщений двусторонних не передавая ссылки (поэтому напрямую объект не передать, свойства не получить). 
  • Передавая объект из PHP в LUA приходится прибегать к registerLibrary (заранее создавать доступные в LUA функции из PHP) и мета таблицам (аналог объектов) при смене или получения значения которых вызвать указанные функции
  • В боевых условиях (кеш, синхронизация данных всех песочниц и тп) простое игровое событие (регенерация) занимает 0.17мс (6000 запросов в секунду где идет вызов LUA и 2 раза обращение в PHP)

V8js (движок для языка JavaScript)

Выполнение компиляции происходит на лету (для примера, использование не рационально):

executeString (отдает фиксированную строку )  140 000 (8 ядер + физ сервер дает x4.5 к скорости)
executeString (отдает получение свойств объекта переданного из PHP)  80 000 (8 ядер + физ сервер дает x5 к скорости)
executeString (отдает выполнение метода объекта переданного из PHP)  40 000 (8 ядер + физ сервер дает x5 к скорости)
execiteString возвращающий анонимную функцию (closure) и вызываемый как метод PHP полученного объекта на 20% быстрее (за счет того что executeString  вызван единожды)

Тоже что и выше но код JS запроса заранее компилируется и его можно использовать повторно:

executeScript (отдает фиксированную строку) 600 000  (8 ядер + физ сервер дает x3.5 к скорости)
executeScript (отдает получение свойств объекта переданного из PHP) 300 000 (8 ядер дают x4 прибавку к скорости)
executeScript (отдает выполнение метода объекта переданного из PHP)  60 000 (8 ядер + физ сервер дает x5 к скорости)
executeScript возвращающий анонимную функцию (closure) на 30% медленнее (в зависимости что возвращает, полагаю особенность компиляции closure)

передача параметров из PHP 700 000 / свойство (8 ядер дают лишь x2.5 прибавку к скорости)

Заметки:
  • Добавлять новые значения из PHP в V8js  - медленно, для экономии времени добавление новых данных можно передать в пространство V8js объект один раз (тк он передастся по ссылке) , а в нем самом уже из PHP менять свойства (это создаст некое хранилище посредник) но свойства должны быть обязательно статичными в этом объекте
  • В данной технологии PHP и V8js делят некое общее хранилище памяти  однако в отличие от LUA объект передается по ссылке и сразу доступен.

Вывод: 

  1. В настоящее время javaScript более популярен за счет игрового движка Phaser2D (33.000 лайков), в то время как для разработки игр где игровые механики (есть движки где LUA используется в незначительной степени для описания действий в игре) написаны на LUA используется Love (3.000 лайков). Lua имеет явный недостаток - это то что для получения свойств объекта PHP нужно вызвать некие функции (как если бы мы взвали методы объектов), но это можно решить кешируя в самом LUA значения , при изменении LUA - менять кеш, при изменении в PHP или JS - отправлять команду на изменение кеша (тк по большей части будет чтение это будет выигрышным выходом). На более мощном железе явный рывок в скорости
  2. В Javascript на рынке много библиотек для работы с физикой, графикой, есть общая память и получение свойств объектов отрабатывает быстро без нужды что либо кешировать (хотя и это тоже можно сделать по примеру LUA). Однако вызов методов объектов PHP явно проигрывает по скорости LUA на хорошем железе, но такие методы вызываются реже (например 1 раз в 200мс) чем читаются (сотни раз в 1мс) и меняются свойства (например раз в кадр 60мс). Пример методов: добавления на карту новых объектов, добавление объекты новых событий, сохранение игрока в базу. 
  3. В LUA можно сделать некий кеш который кеширует все свойство не тратя время на обращение в PHP для их чтения, однако это сопряжено с тем что при смене свойств в JS или PHP мы должны обновлять их в LUA  однако все эти изменения не обязательно обновлять как только они появились , а отправлять пакетом при следующем запуске LUA 
  4. В таких языках как С++ язык LUA встраиваемый (как в нашем сервисе) и старые игры в тч и онлайн до сих пор используют LUA для написания часто меняющейся игровой логики (игровые мероприятия, диалоги, квесты)

Сравнительные тесты CORE (ядра) фреймворка от 02.2021

Результат нагрузочного тестирования HTTP запросами, указан в в миллисекундах (1 секунда = 1000 миллисекунд).

Инструменты SoapUI, 50 потоков, 5 секунд, кеш отключен) на страницу 404.

На Данном примере видно что помимо нагрузки на сервер имеет место тот факт что Laravel и Symfony не успевают освобождать FPM Child (стандартные php fpm с max_children = 5) и создается очередь ожидания освобождения процесса FPM .

Тем самым даже при увеличении числа max_children до достаточного что бы обработать все запросы параллельно скорость выполнения каждого будет равна параметру "min" в табличке ниже на сервере где производилось тестирование. На более мощных серверах и при использовании кэш показатели Symfony и Laravel можно улучшить в Х10 , но не стоит забывать что и показатели фреймворка "Моя Фантазия" вырастут пропорционально. Скорость Symfony и Laravel обусловлена большим количеством библиотек и overhead на роутинг http запросов

Однако скорость обработки запросов в секунду ограничена скоростью HTTP соединений (который работает на базе TCP) и работой самого PHP FPM . Выбрав медленное из них из данных выше можно сделать вывод что 2 миллисекунды (0.002 секунды) на сервере тестирования занимала скорость поднятия такого соединения и она не будет меньше на нем (те чистый результат работы PHP составляя min - 2 )

Laravel 8 : min 266 max 1730 avg 1077

Symfony 5 : min 574 max 4400 avg 2571

"Моя Фантазия" фреймворк : min 7 max 45 avg 10

Новости

Старт продаж наших продуктов и услуг

2023-01-13 01:24:30

Рад сообщить что мы начинаем продавать наши продукты и услуги в частном порядке и оказывать их...

Новая игра на наших продуктах - Metoshi

2023-01-13 01:22:28

На сайт в раздел портфолио добавлена новая игра разработанная с помощью наших продуктов...

Анонс - Бесшовный открытый мир

2022-12-28 14:45:12

Рад сообщить, что игровые карты сервиса будут сделаны по типу "открытого мира", где карты и...

Добавление пользовательского кода Java Script

2022-12-15 18:08:27

Рад сообщить что помимо LUA кода на котором можно писать игровые механики на языке Java Script...

Добавление NPC через LUA код

2022-12-03 21:18:52

Появился видео пример как добавить на карту NPC через код LUA . Эта и другие механики доступны в...

LUA код при входе в игру и добавлении объектов

2022-11-24 18:58:07

Появилась возможность добавить LUA код выполняющийся при добавлении в игру новых игроков, npc,...

Образцы демонстрационных карт и игра The Mana World

2022-11-19 19:33:18

Для тестирования карт и функционала будут использоваться карты из игры с открытом исходным кодом...

Первые результаты интеграция LUA кода

2022-11-19 19:22:16

Рад сообщить что эксперименты по интеграции возможности вносить свой LUA кода в сервер прошли...

Система рассчета PING теперь и в WebGl и новые фичи

2022-11-09 18:47:58

Теперь ping персонажа можно отслеживать и в браузерной версии игры (webgl), так же введена...

Сервер стал быстрее на 80% - асинхронная работа с бд

2022-11-09 18:45:16

Рад сообщить что теперь сохранение игрока (раз в интервал и при выходе) не блокирует сервер как...

Нагрузочное тестирование

2022-11-06 03:48:38

Хочу показать вам результаты нагрузочного тестирования: ·...

Новая механика - ходящие NPC

2022-11-06 03:46:11

Хочу продемонстрировать вам новую игровую механику - блуждание персонажей под управлением...

Ускорение клиентской части

2022-11-06 03:40:28

Рад сообщить что примеры кода к разрабатываемому сервису будут содержать максимальную скорость...

Онлайн редактор карт на WEB

2022-07-18 19:24:29

Ведется разработка web версии редактора карт для 2D.  Конечно, такие вещи уже...

Промежуточные замеры скорости

2022-07-07 17:25:51

Произведены промежуточные замеры скорости (1 секунда = 1000 мс) Данные приведены для сервера с...

Добавление пользовательского LUA кода

2022-07-02 22:40:24

Начата разработка добавления пользовательский скриптов которые можно вешать на объекты. Тем самым...

Все новости

Статьи


  • Создание онлайн сервера для мобильных многопользовательских, realtime 2D игр (жанра RPG и стратегии) с API на PHP ч. 6

    Правительство РФ анонсировало выделение до $50 млрд для выхода РФ в топ-20 стран—разработчиков Игр к 2030 году. Возможно в скором времени разрабатываемый мной сервис наконец увидит свет.

    В этой статье я расскажу как сделать архитектуру приложения игрового сервера быстрой и что использует Unity. Эта статья результаты исследований предыдущих так что в ней будет много ссылок на них.

    Читать далее


  • Создание онлайн сервера для мобильных многопользовательских, realtime 2D игр (жанра RPG и стратегии) с API на PHP ч. 5

    Продолжая серию статей про разработку сервера для онлайн игр (адрес проекта http://my-fantasy.ru) на языке PHP в это части я хочу рассказать про безопасное добавления пользовательского кода для добавления функционала игровых механик. В статье я опишу существующие решения для PHP , сравню скорость работы приведу видео примеры.

    Для тестов будет использовано следующее железо:

    Читать далее


  • Создание онлайн сервера для мобильных многопользовательских, realtime 2D игр (жанра RPG и стратегии) с API на PHP ч. 4

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

    Читать далее


  • Создание онлайн сервера для мобильных многопользовательских, realtime 2D игр (жанра RPG и стратегии) с API на PHP ч. 3

    В 3й части статей я расскажу простым языком про протоколы передачи данных, как они работают и что такое Websocket сервер и какие есть решения для его создания на PHP

    Читать далее


  • Создание онлайн сервера для мобильных многопользовательских, realtime 2D игр (жанра RPG и стратегии) с API на PHP ч. 2

    В этой части будут рассмотрены проблемы с которыми предстоит столкнуться разработчику сервера для онлайн игр

    Для тех кто еще не успел ознакомится с первой частью рублике рекомендую прочитать первую статью где я рассказываю о самой идеи API сервиса.

    Читать далее


  • Создание онлайн сервера для мобильных многопользовательских, realtime 2D игр (жанра RPG и стратегии) с API на PHP ч. 1

    Привет, Хабр! Мой первый пост и я хочу поделиться с вами своей идеей создание сервиса предоставляющего разработчикам игр и студиям платформу для создания онлайн игр! Поехали!

    Читать далее