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.
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
Than 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
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:
- Receive Swoole Request.
- Convert Swoole Request to PSR-7 Request.
- Pass to WordPress Request Handler.
- Receive PSR-7 Response.
- 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:
- Receive Swoole Request.
- Convert Swoole Request to PSR-7 Request.
- Determine if the request is for a special route.
- Use Swoole\Server::task() to send the request to a task worker designated for the special route.
- The task worker passes the request to the WordPress Request Handler.
- Send PSR-7 Response back to main worker.
- Convert to Swoole Response.
php server.php
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.
GPL, see LICENSE.