Бенчмарки и анализ производительности
Научный анализ производительности Localzet Server в различных сценариях использования.
Методология тестирования
Тестовая конфигурация
Оборудование:
- CPU: Intel Xeon E5-2680 v4 (2.4GHz, 14 cores)
- RAM: 64GB DDR4
- Network: 10 Gbps Ethernet
- OS: Ubuntu 22.04 LTS
- PHP: 8.2.x with OPcache enabled
Конфигурация Localzet Server:
$server->count = 14; // По количеству CPU cores
$server->reusePort = true;
TcpConnection::$defaultMaxSendBufferSize = 2097152; // 2MB
TcpConnection::$defaultMaxPackageSize = 10485760; // 10MB
Event Loop: libuv (ext-uv)
Бенчмарки HTTP сервера
Тест 1: Простые GET запросы
Сценарий: Простой HTTP ответ "Hello World"
Результаты:
| Метрика | Значение |
|---|---|
| Requests/sec | 85,000+ |
| Latency (p50) | 0.8ms |
| Latency (p95) | 2.1ms |
| Latency (p99) | 4.5ms |
| Memory per process | 25-30 MB |
| CPU Usage | 85-95% |
Анализ:
- Высокая пропускная способность благодаря event-driven архитектуре
- Низкая латентность за счет минимальной обработки
- Эффективное использование CPU при высокой нагрузке
Тест 2: Динамические запросы с БД
Сценарий: HTTP запросы с запросами к MySQL
Результаты:
| Метрика | Значение |
|---|---|
| Requests/sec | 12,000+ |
| Latency (p50) | 5.2ms |
| Latency (p95) | 18.5ms |
| Latency (p99) | 45.0ms |
| Memory per process | 40-50 MB |
| DB Connections | 14 (по одному на процесс) |
Оптимизация:
- Connection pooling: переиспользование соединений с БД
- Подготовленные запросы для минимизации парсинга
- Кеширование частых запросов
Тест 3: Файловые ответы
Сценарий: Отправка файлов различных размеров
Результаты:
| Размер файла | Throughput | Memory Usage |
|---|---|---|
| 1 KB | 75,000 req/s | 25 MB |
| 100 KB | 45,000 req/s | 30 MB |
| 1 MB | 8,000 req/s | 35 MB |
| 10 MB | 1,200 req/s | 40 MB |
| 100 MB | 150 req/s | 45 MB |
Наблюдения:
- Для файлов < 2MB: отправка из памяти
- Для файлов > 2MB: потоковая передача
- Постоянное потребление памяти независимо от размера файла
Бенчмарки WebSocket сервера
Тест 1: Количество соединений
Сценарий: Максимальное количество одновременных WebSocket соединений
Результаты:
| Процессов | Соединений на процесс | Всего соединений | Memory/Process |
|---|---|---|---|
| 1 | 50,000+ | 50,000+ | 180 MB |
| 4 | 50,000+ | 200,000+ | 180 MB |
| 14 | 50,000+ | 700,000+ | 180 MB |
Выводы:
- Каждый процесс может обрабатывать десятки тысяч соединений
- Потребление памяти линейно от количества соединений
- Минимальные накладные расходы на соединение (~3-4 KB)
Тест 2: Частота сообщений
Сценарий: Broadcast сообщений всем подключенным клиентам
Результаты:
| Соединений | Сообщений/сек | Latency (p99) |
|---|---|---|
| 1,000 | 100,000+ | 5ms |
| 10,000 | 500,000+ | 12ms |
| 50,000 | 1,000,000+ | 45ms |
Оптимизация:
- Эффективная итерация по соединениям: O(N)
- Минимизация системных вызовов через буферизацию
- Параллельная обработка в нескольких процессах
Сравнение с альтернативами
Localzet Server vs PHP-FPM + Nginx
Тест: Простые HTTP запросы
| Метрика | Localzet | PHP-FPM+Nginx | Улучшение |
|---|---|---|---|
| Requests/sec | 85,000 | 15,000 | 5.7x |
| Latency (p50) | 0.8ms | 3.2ms | 4x быстрее |
| Memory/req | ~0.3 KB | ~2 KB | 6.7x меньше |
| CPU efficiency | 90% | 65% | 1.4x лучше |
Преимущества Localzet:
- Меньше накладных расходов (нет проксирования)
- Переиспользование памяти
- Прямая обработка без промежуточных слоев
Localzet Server vs Node.js
Тест: WebSocket соединения
| Метрика | Localzet | Node.js | Разница |
|---|---|---|---|
| Connections/process | 50,000+ | 60,000+ | -17% |
| Messages/sec | 1,000,000+ | 1,200,000+ | -17% |
| Memory/connection | ~3.6 KB | ~3.2 KB | +12% |
| Startup time | ~0.5s | ~0.1s | +400% |
Выводы:
- Node.js имеет преимущество благодаря V8
- Localzet Server сопоставим по производительности
- Преимущество PHP: знакомый язык для многих разработчиков
Анализ масштабируемости
Горизонтальное масштабирование
Тест: Увеличение количества серверов
1 сервер (14 процессов): 85,000 req/s
2 сервера: 165,000 req/s (97% эффективность)
4 сервера: 320,000 req/s (94% эффективность)
8 серверов: 600,000 req/s (88% эффективность)
Формула эффективности:
Efficiency = Actual_Throughput / (N × Single_Server_Throughput)
где:
N - количество серверов
Причины снижения эффективности:
- Overhead балансировки нагрузки
- Сетевая задержка между серверами
- Координационные издержки
Вертикальное масштабирование
Тест: Увеличение количества процессов
1 процесс: 6,000 req/s
4 процесса: 24,000 req/s (100% эффективность)
8 процессов: 47,000 req/s (98% эффективность)
14 процессов: 85,000 req/s (97% эффективность)
Вывод: Оптимальное количество процессов = количество CPU cores
Анализ производительности протоколов
HTTP/1.1 Performance
Факторы производительности:
-
Парсинг запросов:
- Без кеша: ~0.1ms на запрос
- С кешем: ~0.01ms на запрос (10x ускорение)
-
Формирование ответов:
- Простой ответ: ~0.05ms
- Ответ с заголовками: ~0.1ms
- Файловый ответ: зависит от размера
WebSocket Performance
Overhead фреймов:
Frame_Overhead = 2-14 bytes (заголовок)
Payload_Efficiency = Payload_Size / (Payload_Size + Frame_Overhead)
Для 100 байт сообщения:
Efficiency = 100 / (100 + 6) = 94.3%
Производительность:
- Handshake: ~2ms (один раз)
- Отправка сообщения: ~0.05ms
- Получение сообщения: ~0.03ms
Оптимизации и их эффект
Использование libuv
Улучшение производительности:
| Операция | stream_select | libuv | Улучшение |
|---|---|---|---|
| I/O events | O(N) | O(M) где M << N | До 100x |
| Timers | O(N) | O(log N) | До 10x |
| Signals | N/A | Native | - |
SO_REUSEPORT
Распределение нагрузки:
Без SO_REUSEPORT:
- Все процессы конкурируют за accept()
- Thunder herd проблема
С SO_REUSEPORT:
- Распределение на уровне ядра
- 15-20% улучшение производительности
Кеширование запросов
Эффективность кеша:
Cache_Hit_Rate = f(Request_Patterns)
Для типичного веб-приложения:
Hit_Rate ≈ 30-50%
Экономия CPU:
CPU_Saved = Hit_Rate × Parse_Cost
≈ 30% × Parse_Cost
Энергоэффективность
Потребление ресурсов
CPU Utilization:
Idle: 5-10% CPU
Low load: 20-40% CPU
Medium load: 60-80% CPU
High load: 85-95% CPU
Memory Efficiency:
Memory_Per_Connection ≈ 3-4 KB
для 10,000 соединений:
Total_Memory ≈ 35-40 MB
Сравнение энергопотребления
Нагрузка: 50,000 req/s
| Метрика | Localzet | PHP-FPM+Nginx | Разница |
|---|---|---|---|
| CPU Cores used | 12 | 16 | -25% |
| Memory | 480 MB | 1.2 GB | -60% |
| Power (est.) | ~150W | ~200W | -25% |
Рекомендации на основе бенчмарков
Оптимальные настройки
Для высоких нагрузок:
$server->count = cpu_count();
$server->reusePort = true;
// Оптимальные размеры буферов
TcpConnection::$defaultMaxSendBufferSize = 4194304; // 4MB
TcpConnection::$defaultMaxPackageSize = 20971520; // 20MB
// Использование libuv
// Установить: pecl install uv
Для низкой латентности:
$server->count = cpu_count();
// Минимизация обработки в onMessage
// Использование кешей
// Оптимизация протоколов
Избегайте
- Слишком много процессов (более CPU × 2)
- Блокирующие операции в обработчиках
- Большие синхронные вычисления
- Неоптимальные протоколы
Метрики для мониторинга
Ключевые показатели (KPI)
// Throughput
$throughput = $stats['total_request'] / $uptime;
// Latency distribution
$latencies = collectLatencies(); // Реализация зависит от приложения
$p50 = percentile($latencies, 50);
$p95 = percentile($latencies, 95);
$p99 = percentile($latencies, 99);
// Resource utilization
$cpu_avg = sys_getloadavg()[0];
$memory_current = memory_get_usage(true);
$memory_peak = memory_get_peak_usage(true);
// Error rate
$error_rate = $stats['throw_exception'] / $stats['total_request'];
Алерты
// Настройка алертов
if ($throughput < THRESHOLD_THROUGHPUT) {
alert('Low throughput detected');
}
if ($p99 > THRESHOLD_P99_LATENCY) {
alert('High latency detected');
}
if ($memory_current > THRESHOLD_MEMORY) {
alert('High memory usage');
}
Результаты в реальных условиях
Production статистика
Типичное веб-приложение:
- Requests/sec: 10,000-20,000
- Concurrent connections: 5,000-10,000
- Average latency: 10-30ms
- P99 latency: 100-200ms
- Memory usage: 200-400 MB per process
- CPU usage: 40-60% average
Высоконагруженное приложение:
- Requests/sec: 50,000-100,000
- Concurrent connections: 20,000-50,000
- Average latency: 5-15ms
- P99 latency: 50-100ms
- Memory usage: 300-500 MB per process
- CPU usage: 70-90% average
Заключение
Localzet Server демонстрирует:
- Высокую производительность: Сопоставим с Node.js
- Эффективность памяти: Минимальные накладные расходы
- Масштабируемость: Линейное масштабирование до десятков процессов
- Надежность: Отказоустойчивость через изоляцию процессов
Эти характеристики делают Localzet Server подходящим для:
- Высоконагруженных веб-приложений
- Real-time систем
- IoT платформ
- Микросервисных архитектур

