WordPress running on the High performance HTTP server based on Swoole.

Maintainers

Package info

github.com/WordPress-PSR/swoole

Type:project

pkg:composer/wordpress-psr/swoole

Statistics

Installs: 524

Dependents: 0

Suggesters: 0

Stars: 85

Open Issues: 2


README

A method of running WordPress with the high performance, event-driven Swoole HTTP Server. This project is very much a work in progress, and many bugs can be expected. Pull requests are very welcome.

Quick Start (Docker)

The fastest way to get a working development environment is with Docker.

Requirements: Docker and Docker Compose v2.

# 1. Clone the project
git clone https://github.com/WordPress-PSR/swoole.git wordpress-swoole
cd wordpress-swoole

# 2. (Optional) Customise configuration
cp .env.example .env
# Edit .env to change ports, credentials, etc.

# 3. Start all services
docker compose up -d

# 4. Visit the site
open http://localhost:8889

WordPress is installed automatically on first boot. Default credentials:

Setting Value
URL http://localhost:8889
Username admin
Password password

Hot reload is enabled by default via inotify — PHP file changes trigger an automatic server reload without restarting the container.

Database data persists between restarts in a named Docker volume.

Useful commands

# View logs
docker compose logs -f app

# Run WP-CLI commands
docker compose exec app wp --info --allow-root

# Stop services
docker compose down

# Destroy everything including the database volume
docker compose down -v

Redis (optional)

To enable Redis for object cache testing, uncomment the redis service block in docker-compose.yml.

Manual Installation

Swoole must be installed from pecl or another source.

composer create-project -s dev wordpress-psr/swoole wordpress-swoole

Start swoole process

cd wordpress-swoole
php server.php

Visit http://0.0.0.0:8889/ It should redirect to configure and perform WordPress's famous 5-minute installation. If it fails for any reason create wp-config.php manually.

cp wordpress/wp-config-sample.php wp-config.php

Then run the installation with WP-CLI.

wp core install --url='http://0.0.0.0:8889' --title='Swoole Test' --admin_user=admin --admin_password=password --skip-email

Overview

Most of the heavy lifting is done by WordPress PSR Request Handler. This project is mostly just glue that pieces the request handler with the chubbyphp-swoole-request-handler. The basic flow goes like this:

  1. Receive Swoole Request.
  2. Convert Swoole Request to PSR-7 Request.
  3. Pass to WordPress Request Handler.
  4. Receive PSR-7 Response.
  5. Convert to Swoole Response.

Because of the way WordPress makes use of constants such as WP_ADMIN to designate the source of some requests a system was developed to route certain requests to specific workers, so the admin would be served by a separate pool from the frontend. In the case the flow looks like:

  1. Receive Swoole Request.
  2. Convert Swoole Request to PSR-7 Request.
  3. Determine if the request is for a special route.
  4. Use Swoole\Server::task() to send the request to a task worker designated for the special route.
  5. The task worker passes the request to the WordPress Request Handler.
  6. Send PSR-7 Response back to main worker.
  7. Convert to Swoole Response.

Running

php server.php

Performance

About 2X better. A simple ab of the homepage with only the base install data shows 695 requests pre second running WordPress on Swoole vs 324 running php-fpm. Nginx+php-fpm:

ab -n 10000 -c 8 http://pm.localhost:8088/

Server Software:        nginx/1.16.1
Server Hostname:        pm.localhost
Server Port:            8088

Document Path:          /
Document Length:        8570 bytes

Concurrency Level:      8
Time taken for tests:   30.841 seconds
Complete requests:      10000
Failed requests:        0
Total transferred:      88020000 bytes
HTML transferred:       85700000 bytes
Requests per second:    324.25 [#/sec] (mean)
Time per request:       24.672 [ms] (mean)
Time per request:       3.084 [ms] (mean, across all concurrent requests)
Transfer rate:          2787.14 [Kbytes/sec] received

Connection Times (ms)
min  mean[+/-sd] median   max
Connect:        0    0   0.0      0       0
Processing:    12   25   3.6     25      38
Waiting:       12   24   3.6     25      38
Total:         12   25   3.6     25      38

Percentage of the requests served within a certain time (ms)
50%     25
66%     26
75%     27
80%     28
90%     29
95%     30
98%     32
99%     32
100%     38 (longest request)

Swoole:

ab -n 10000 -c 8 http://0.0.0.0:8889/

Server Software:        swoole-http-server
Server Hostname:        0.0.0.0
Server Port:            8889

Document Path:          /
Document Length:        6256 bytes

Concurrency Level:      8
Time taken for tests:   14.383 seconds
Complete requests:      10000
Failed requests:        3996
   (Connect: 0, Receive: 0, Length: 3996, Exceptions: 0)
Total transferred:      64911212 bytes
HTML transferred:       62561212 bytes
Requests per second:    695.28 [#/sec] (mean)
Time per request:       11.506 [ms] (mean)
Time per request:       1.438 [ms] (mean, across all concurrent requests)
Transfer rate:          4407.40 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.0      0       1
Processing:     7   11  11.8     11     448
Waiting:        7   11  11.8     11     448
Total:          7   11  11.8     11     448

Percentage of the requests served within a certain time (ms)
  50%     11
  66%     11
  75%     11
  80%     12
  90%     12
  95%     12
  98%     13
  99%     15
 100%    448 (longest request)

Above tests were run with PHP 7.4.15, swoole 4.6.4 on an i7-1065G7 CPU.

License

GPL, see LICENSE.