Performance tuning#
This documentation applies to Piler enterprise edition 1.8.x
Revision #1
Publication date: 2025-09-26
In the below example, we optimise for a 2 vCPU + 2 GB RAM box for high concurrency without exhausting memory
Tuning nginx#
/etc/nginx/nginx.conf:
events {
worker_connections 4096; # worker_connections * worker_processes = max simultaneous connections
multi_accept on; # accept as many as possible
use epoll; # (Linux only, usually auto-detected)
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
keepalive_requests 10000;
client_max_body_size 4M;
client_body_buffer_size 128k;
client_header_buffer_size 4k;
large_client_header_buffers 4 16k;
# Buffers for fastcgi (PHP-FPM)
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
fastcgi_busy_buffers_size 64k;
fastcgi_temp_file_write_size 64k;
fastcgi_connect_timeout 30s;
fastcgi_send_timeout 30s;
fastcgi_read_timeout 30s;
}
Tuning PHP#
/etc/php/8.3/fpm/pool.d/www.conf:
; --- Process management ---
pm = dynamic
pm.max_children = 40 ; hard cap on workers, prevents OOM
pm.start_servers = 6 ; reasonable initial pool
pm.min_spare_servers = 6
pm.max_spare_servers = 20
; --- Recycling ---
pm.max_requests = 500 ; recycle workers to avoid leaks
; --- Timeouts ---
request_terminate_timeout = 30s
request_slowlog_timeout = 10s
slowlog = /var/log/php8.3-fpm.slow.log
; --- Logging ---
catch_workers_output = yes
; --- Resource limits ---
rlimit_files = 65535
rlimit_core = 0
; --- PHP INI overrides (per pool) ---
php_admin_value[memory_limit] = 256M ; cap memory per worker
php_admin_value[max_execution_time] = 30
php_admin_value[post_max_size] = 4M
php_admin_value[upload_max_filesize] = 4M
php_admin_value[expose_php] = 0
; PHP-FPM status page
pm.status_path = /php-fpm-status
ping.path = /ping
ping.response = pong
/etc/php/8.3/fpm/php.ini:
opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=256 ; shared memory in MB
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=20000
opcache.validate_timestamps=1 ; check file changes
opcache.revalidate_freq=2
opcache.fast_shutdown=1
realpath_cache_size=4096k
realpath_cache_ttl=600
Key points:#
pm.max_children = 40 → with 2 GB RAM and ~30–40 MB per worker under search load, this is safe.
pm.max_requests = 500 → prevents long-lived workers from fragmenting memory.
Memory cap (memory_limit = 256M) → ensures no runaway scripts eat too much.
rlimit_files raised → nginx + php-fpm under load can otherwise hit "Too many open files" error.
Enable php-fpm status#
/etc/piler/piler-nginx:
location ~ ^/(php-fpm-status|ping)$ {
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
allow 127.0.0.1;
deny all;
}
Check metrics:
curl http://127.0.0.1/php-fpm-status
The result is something like
pool: www
process manager: dynamic
start time: 15/Sep/2025:12:00:00 +0000
accepted conn: 10234
listen queue: 0
max children reached: 0
active processes: 12
idle processes: 8
Key fields:
listen queue > 0 → requests are waiting (too few workers).
max children reached > 0 → all workers were busy (raise pm.max_children).
active processes close to max_children under load → you’re at capacity.