monorepo/native/wordpress/maplepress-plugin/docs/PERFORMANCE_OPTIMIZATION.md

8.8 KiB

MaplePress Performance Optimization Guide

Understanding WordPress Performance Bottlenecks

MaplePress offloads search processing to our cloud infrastructure, but your WordPress site's ability to handle concurrent requests determines the actual user experience. Even with our lightning-fast backend (< 20ms processing time), users may experience slow response times if WordPress itself is the bottleneck.


The #1 Bottleneck: PHP-FPM Worker Starvation

What is PHP-FPM?

PHP-FPM (FastCGI Process Manager) is the process manager that handles PHP requests in WordPress. It uses a pool of "worker" processes to execute PHP code.

Think of it like a restaurant:

  • Chef (PHP-FPM worker) = processes one request at a time
  • Order (HTTP request) = incoming search/page load

If you have 5 chefs and 25 orders arrive simultaneously, only 5 orders get processed immediately. The other 20 orders wait in line (queue), even if each order only takes 200ms to prepare.

Real-World Impact

Common Default Configuration:

pm.max_children = 5    # Only 5 workers!

What This Means:

  • Concurrent users: 25 people search simultaneously
  • Workers available: Only 5
  • Result: 20 requests wait in queue
  • User experience: 8-10 second response times (even though backend is fast!)

Performance Comparison (25 concurrent searches):

Configuration Workers Response Time Queue Time
Default 5 8,000-9,000ms ~7,800ms waiting
Optimized 50 300-500ms No waiting

52x faster just by increasing workers!


Solution: Increase PHP-FPM Workers

Step 1: Check Current Configuration

SSH into your WordPress server:

# For standard PHP-FPM installations
sudo cat /etc/php/*/fpm/pool.d/www.conf | grep -E "^pm\.|^pm "

# For Docker (check inside container)
docker exec your-wordpress-container cat /usr/local/etc/php-fpm.d/www.conf | grep -E "^pm\.|^pm "

Look for these values:

pm = dynamic
pm.max_children = 5          # ← This is usually the problem!
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3

Step 2: Calculate Optimal Worker Count

Formula:

pm.max_children = (Available RAM) / (Average PHP Memory per Process)

Example Calculations:

2GB Server:

  • Total RAM: 2048 MB
  • System RAM: ~512 MB
  • Available: 1536 MB
  • PHP Memory per Process: ~70 MB
  • Recommended: pm.max_children = 20-25

4GB Server:

  • Total RAM: 4096 MB
  • System RAM: ~512 MB
  • Available: 3584 MB
  • PHP Memory per Process: ~70 MB
  • Recommended: pm.max_children = 50

8GB Server:

  • Total RAM: 8192 MB
  • System RAM: ~512 MB
  • Available: 7680 MB
  • PHP Memory per Process: ~70 MB
  • Recommended: pm.max_children = 100

Step 3: Apply Configuration

For Docker Deployments (Recommended):

Create /opt/wordpress/php-fpm-custom.conf:

[www]
pm = dynamic
pm.max_children = 50              ; Adjust based on your RAM
pm.start_servers = 10             ; Start with 10 workers
pm.min_spare_servers = 5          ; Keep at least 5 idle
pm.max_spare_servers = 20         ; Keep at most 20 idle
pm.max_requests = 500             ; Recycle workers after 500 requests

; Logging for debugging
pm.status_path = /status
ping.path = /ping
ping.response = pong

Mount it in docker-compose.yml:

wordpress:
  volumes:
    - ./php-fpm-custom.conf:/usr/local/etc/php-fpm.d/zz-custom.conf:ro

Restart: docker compose restart wordpress

For Standard PHP-FPM Installations:

# Edit PHP-FPM config (adjust PHP version as needed)
sudo nano /etc/php/8.2/fpm/pool.d/www.conf

# Find and modify:
pm = dynamic
pm.max_children = 50
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20
pm.max_requests = 500

# Restart PHP-FPM
sudo systemctl restart php8.2-fpm

# Verify
sudo systemctl status php8.2-fpm

Step 4: Verify Changes

# Check running PHP-FPM processes
ps aux | grep php-fpm | wc -l
# Should show 10+ processes initially

# During load test, monitor scaling
watch -n 1 "ps aux | grep php-fpm | wc -l"
# Should scale up to match traffic

Additional Optimizations

1. Enable OpCache (PHP Bytecode Cache)

OpCache compiles PHP code once and caches it, avoiding recompilation on every request.

Configuration (/etc/php/8.2/fpm/php.ini):

opcache.enable = 1
opcache.memory_consumption = 256          ; 256MB for cache
opcache.max_accelerated_files = 20000     ; Cache up to 20k files
opcache.validate_timestamps = 0           ; Don't check for file changes (production)
opcache.revalidate_freq = 0
opcache.fast_shutdown = 1

Expected Impact: 30-50% faster PHP execution

2. Optimize Nginx (if applicable)

worker_processes auto;               # Use all CPU cores
worker_connections 1024;             # Handle 1024 connections per worker

# Enable gzip compression
gzip on;
gzip_vary on;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml text/javascript application/json application/javascript;

3. Increase MySQL Connections

If you see "too many connections" errors:

sudo nano /etc/mysql/my.cnf

[mysqld]
max_connections = 200

sudo systemctl restart mysql

4. Monitor Resource Usage

# CPU and memory usage
htop

# PHP-FPM status (if enabled)
curl http://localhost/status?full

# Disk I/O
iostat -x 1

# Network usage
iftop

Testing Your Optimization

Before and After Comparison

Test Tool: MaplePress CLI wptest command

cd native/desktop/maplepress-cli

# Run concurrent test (25 simultaneous requests)
go run main.go wptest --url https://your-site.com --mode parallel --concurrency 25

Expected Results:

Metric Before After (Optimized) Improvement
Average Response 8,000ms 300-500ms 16-27x faster
P95 Latency 9,000ms < 1,000ms 9x faster
Concurrent Handling Queues 20/25 Handles all 25 No queuing

In-Plugin Speed Test

Use the built-in MaplePress → Speed Test page in WordPress admin:

  1. Go to MaplePressSpeed Test
  2. Select number of trials (10-20 recommended)
  3. Click Run Speed Test
  4. Review results and recommendations

Common Performance Issues

Issue: High PHP Memory Usage

Symptoms:

  • PHP workers crash with "out of memory"
  • WordPress shows white screen/500 errors

Solutions:

# Reduce worker count
pm.max_children = 25  # Instead of 50

# Or increase PHP memory limit
memory_limit = 256M   # In php.ini

Issue: Still Slow After Optimization

Check:

  1. Database queries: Slow plugins, missing indexes

    # Enable MySQL slow query log
    slow_query_log = 1
    slow_query_log_file = /var/log/mysql/slow.log
    long_query_time = 1
    
  2. Caching: Aggressive caching can hide PHP-FPM issues

    • Clear all caches and test
    • Disable page caching temporarily
  3. Network latency: Test from different locations

    curl -w "@curl-format.txt" -o /dev/null -s https://your-site.com
    
  4. Resource limits: Check if hitting CPU/RAM limits

    # Monitor during load test
    top
    free -h
    

Production Deployment Checklist

  • PHP-FPM pm.max_children increased (≥ 25 for 2GB, ≥ 50 for 4GB)
  • OpCache enabled and configured
  • Nginx worker_processes set to auto
  • MySQL max_connections increased (≥ 200)
  • Caching strategy reviewed (not hiding problems)
  • Monitoring tools installed (htop, iotop, iftop)
  • Load testing performed (wptest with concurrency 25+)
  • Resource usage monitored under load
  • Backup/rollback plan in place

Additional Resources

WordPress Documentation

MaplePress Resources

  • Production Deployment Guide: See cloud/infrastructure/production/setup/08_wordpress.md in the MaplePress repository
  • MaplePress CLI: Speed testing and diagnostics tool
  • Support: Contact MaplePress support for optimization assistance

Performance Tools

  • htop: Interactive process viewer
  • iotop: Disk I/O monitoring
  • iftop: Network bandwidth monitoring
  • MySQL Tuner: mysqltuner.pl for database optimization

Summary

The #1 performance issue is PHP-FPM worker starvation, not backend speed.

MaplePress backend processes searches in < 20ms, but if your WordPress site only has 5 PHP-FPM workers and receives 25 concurrent requests, users will wait 8-10 seconds while requests queue.

Quick Win: Increase pm.max_children from 5 to 50 (on 4GB server) for 16-27x faster response times.

Your MaplePress subscription includes a lightning-fast backend. Ensure your WordPress frontend can keep up!