First look at Swoole
October 22, 2018
Following on from my previous post on roadrunner. I’ve since been made aware of Swoole. Swoole bills itself as a “Production-Grade Async programming Framework for PHP”. I confess that when I first became aware of Swoole, I dismissed it as another ReactPHP/Icicle/Amp nginx fraemwork, but written as an extension.
However, if you actually look at this diagram it shows that there is much more going on than just an async loop. The Swoole framework actually manages to make the process of many master and worker processes (as I described in Roadrunner) as seamless as a few lines of callback-like code.
Observe the simple example given in the documentation:
1<?php
2$http = new swoole_http_server("127.0.0.1", 9501);
3
4$http->on("start", function ($server) {
5 echo "Swoole http server is started at http://127.0.0.1:9501\n";
6});
7
8$http->on("request", function ($request, $response) {
9 $response->header("Content-Type", "text/plain");
10 $response->end("Hello World\n");
11});
12
13$http->start();
This would appear to run a simple loop, then run the anonymous function on an HTTP request. However, reality is a bit different:
1$ php test-swoole.php
2Swoole http server is started at http://127.0.0.1:9501
3^Z
4[1]+ Stopped php test-swoole.php
5$ ps aux | grep test-swoole | grep -v grep
6scottaubrey 2500 0.0 0.0 4372096 892 s003 T 9:09am 0:00.00 php test-swoole.php
7scottaubrey 2499 0.0 0.0 4363904 928 s003 T 9:09am 0:00.00 php test-swoole.php
8scottaubrey 2498 0.0 0.0 4369932 620 s003 T 9:09am 0:00.00 php test-swoole.php
9scottaubrey 2497 0.0 0.1 4382108 24204 s003 T 9:09am 0:00.06 php test-swoole.php
10scottaubrey 2502 0.0 0.0 4363904 928 s003 T 9:09am 0:00.00 php test-swoole.php
11scottaubrey 2501 0.0 0.0 4363904 900 s003 T 9:09am 0:00.00 php test-swoole.php
As you can see, by running the script, there are actually 6 PHP processes created. This allows the half-way house of async PHP application server that Roadrunner allows. In fact, my early experiments with Swoole are extremely promising.
Benchmark
I’ll create another fairly useless, unscientific benchmark, using a simple, real-life web application home page (PSR-15 pipeline, router, single template, no database) under PHP built-in server, roadrunner and swoole. Using a single thread, and only 1 connection to try not disadvantage the PHP application server, we run 30 seconds of requests:
PHP built-in server:
1$ wrk -t1 -c1 -d30s http://127.0.0.1:8000
2Running 30s test @ http://127.0.0.1:8000
3 1 threads and 1 connections
4 Thread Stats Avg Stdev Max +/- Stdev
5 Latency 3.95ms 571.20us 14.39ms 97.05%
6 Req/Sec 196.00 92.30 252.00 81.40%
7 881 requests in 30.07s, 5.61MB read
8 Socket errors: connect 0, read 881, write 0, timeout 0
9Requests/sec: 29.30
10Transfer/sec: 191.05KB
Roadrunner
1$ wrk -t1 -c1 -d30s http://127.0.0.1:8888
2Running 30s test @ http://127.0.0.1:8888
3 1 threads and 1 connections
4 Thread Stats Avg Stdev Max +/- Stdev
5 Latency 579.84us 131.64us 7.19ms 94.74%
6 Req/Sec 1.71k 79.31 1.81k 85.38%
7 51285 requests in 30.10s, 325.20MB read
8Requests/sec: 1703.73
9Transfer/sec: 10.80MB
Swoole:
1$ wrk -t1 -c1 -d30s http://127.0.0.1:8080
2Running 30s test @ http://127.0.0.1:8080
3 1 threads and 1 connections
4 Thread Stats Avg Stdev Max +/- Stdev
5 Latency 166.20us 41.18us 2.72ms 97.17%
6 Req/Sec 5.95k 267.90 6.21k 93.69%
7 178314 requests in 30.10s, 1.11GB read
8Requests/sec: 5924.05
9Transfer/sec: 37.75MB
Remember, most of this speed up should be coming from not re-bootstrapping the application on each request. The >50x faster Roadrunner becomes a whopping 4x faster still with Swoole, or 200x faster than the PHP application server.
I confess, I really don’t know of the quality of Swoole’s HTTP server, but the capability to “start” your own server, combined with the tidy performance improvement lets me think that Swoole is worth giving a try.