Анализ технологий обмена данных между процессами 

Mysql

~600 запись среднестатистического пакет данных игрока

PS Имеется возможность работы в асинхронном режиме (без ожидания записи чтения) благодаря расширениям от Swoole и др основанным на асинхрнном TCP взаимодействии


Redis

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

PS Имеется возможность работы в асинхронном режиме, максимальный RPS ~100 000 согласно официальным тестам


ZeroMQ

pub sub 300 000 (в асинхронном, неблокируемом режиме согласно публичным тестам

RabbitMQ

до 60.000 согласно официальным данным, для текущего железа ожидалось бы ~6 000

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

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

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

get 700 000

Libevent (событийная модель)

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

Swoole Timer (событийная модель)

...

Parallel (работа на разных ядрах CPU параллельно, обмен данных посредством каналов наподобии как в языке GO)

send (отправка данных на исполнение в отдельный поток)  1 600 000 запросов в секунду (без учета времени на чтение этих данных параллельным потоком)

Обычная переменная (для сравнения)

get 70 000 000

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

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

Анализ скорости работы стандартных функций базового языка на котором написан сервер - 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_diff_key 10 000 000 (5 значений)
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 соединения асинхронно но с потерей порядка записи)



Что нового?


Статьи про разработку продукта

PHP, Программирование, Разработка игр, Unity, Unreal Engine, php, игровой сервер, разработка сервисов, онлайн-игры, разработка онлайн-игр

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

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

Бонус - архитектура игрового сервера в картинках.

Читать далее
Создание сервера для онлайн ММО игр на PHP ч.14 — Сетевая карта и задержка кадра (Latency frame) по RFC 2544 (1242)
PHP, Проектирование и рефакторинг, Разработка игр, Сетевые технологии, Параллельное программирование, php, go, c#, онлан игры
Создание сервера для онлайн ММО игр на PHP ч.13 — Event-driven паттерн, JSON-RPC и почему не сервисная (SOA) архитектура
PHP, Программирование, Проектирование и рефакторинг, Разработка игр, Алгоритмы, php, event-driven, разработка игр, mmo, mmorpg, шаблон проектирования
Создание сервера для онлайн ММО игр на PHP ч. 12 — Очереди и параллельное программирование на CPU
PHP, Анализ и проектирование систем, Разработка игр, Сетевые технологии, Параллельное программирование, php, go, онлайн-игры, очереди, очереди задач, очереди сообщений, очереди с приоритетом, websocket, unity, ммо

Кабинет

Игры