Penggunaan fungsi SWOOLE pada PHP

Pada artikel ini kita akan melakukan benchmark PHP Swoole vs NodeJs vs Go. Benchmark yang dilakukan adalah benchmark sederhana yaitu masing-masing bahasa pemrograman mengembalikan sebuah string “Welcome to hello world benchmark.”

Meskipun benchmark ini tidak menggambarkan kondisi aplikasi real world pada umumnya. Namun paling tidak benchmark ini dapat mengindikasikan bagaimana performa dasar dari setiap bahasa pemograman.

Artikel ini juga dapat dibaca pada website TeknoCerdas.com.

Sekilas Tentang PHP Swoole, NodeJS dan Go

Swoole adalah sebuah asynchronus framework berbasis co-routine untuk PHP. Swoole ditulis menggunakan C dan dan didistribusikan dalam bentuk eksensi untuk PHP. Untuk menggunakannya pengguna harus melakukan instalasi lewat pecl.

NodeJS adalah sebuah runtime Javascript yang mendukung asynchronous event-driven dan non-blocking I/O. NodeJS dibangun diatas javascript engine yang digunakan oleh Chrome yaitu V8.

Go atau Golang adalah sebuah bahasa pemrograman open source yang dikembangkan oleh Google. Go mendukung concurency secara default melalui apa yang disebut sebagai goroutine atau channel.

Konfigurasi Benchmark

Terdapat dua mesin dalam konfigurasi benchmark yang dilakukan. Satu mesin untuk hosting aplikasi server yang dibuat pada masing-masing bahasa pemrograman. Satu lagi untuk menjalankan HTTP load testing menggunakan Apache Bench (ab).

Benchmark ini dilakukan menggunakan layanan AWS cloud dengan tipe instance c5d.2xlarge. Berikut spesifikasi untuk kedua mesin yang digunakan.

+------------+------------------------------------------------+
| CPU | Intel(R) Xeon(R) Platinum 8275CL CPU @ 3.00GHz |
|------------|------------------------------------------------|
| Core | 8 cores |
|------------|------------------------------------------------|
| RAM | 16 GB |
|------------|------------------------------------------------|
| Disk | 8 GB nvme |
|------------|------------------------------------------------|
| Local CIDR | 172.31.0.0/16 |
|------------|------------------------------------------------|
| OS | Ubuntu 18.04 LTS |
+------------+------------------------------------------------+

Konfigurasi kernel yang digunakan baik untuk application server atau client.

cat <<EOF | tee /etc/sysctl.conf
fs.file-max=2097152
net.ipv4.tcp_synack_retries=2
net.ipv4.ip_local_port_range = 2000 65535
net.ipv4.tcp_rfc1337=1
net.core.somaxconn=65535
net.core.netdev_max_backlog=65536
net.ipv4.tcp_slow_start_after_idle=0
net.ipv4.tcp_slow_start_after_idle=0
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_fin_timeout = 5
vm.swappiness = 0
EOF

Script untuk PHP Swoole

Versi PHP yang digunakan adalah PHP v7.4.5 dan Swoole v4.5.0.

$ cat > hello.php
<?php
$http = new Swoole\HTTP\Server('0.0.0.0', 8081);
$http->on('request', function ($request, $response) {
$response->end('Welcome to hello world benchmark.');
});
echo '> Starting Swoole HTTP server...';
$http->start();

Script untuk NodeJS

Versi NodeJS yang digunakan adalah v12.16.3.

$ cat > hello.js
const http = require('http');
const requestListener = function (req, res) {
res.writeHead(200);
res.end('Welcome to hello world benchmark.');
}
const server = http.createServer(requestListener);
process.stdout.write('> Starting Node HTTP server...')
server.listen(8082, '0.0.0.0');

Script untuk Go

Versi Go yang digunakan adalah v1.14.2.

$ cat > hello.go
package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/", func (w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Welcome to hello world benchmark.")
})
fmt.Print("> Starting Go HTTP server...")
http.ListenAndServe("0.0.00:8083", nil)
}

Menjalankan Benchmark

Benchmark dijalankan secara bergantian artinya hanya ada satu server aplikasi yang jalan pada satu waktu. Sebagai contoh ketika melakukan benchmark pada PHP Swoole maka server NodeJS dan Go dimatikan. Hal ini untuk memberikan gambaran yang lebih adil terutama penggunaan memori.

Berikut cara Saya menjalankan benchmark untuk masing-masing http server. Setiap benchmark diulang 3 kali tanpa mematikan http server. Setiap akan diulang cache memory dibersihkan dengan perintah.

$ echo 2 > sudo tee /proc/sys/vm/drop_caches

Sebelum memulai lagi saya juga memastikan bahwa semua network socket yang ada sudah bersih dan tidak ada yang menunggu.

$ sudo netstat -ntap | grep WAIT

Jika tidak socket yang tergantung maka benchmark dapat dimulai. Hal ini untuk menghindari limit open_max_files. Karena setiap socket yang dibuka juga merupakan sebuah file di sistem operasi berbasi *NIX.

Memulai benchmark pada masing-masing HTTP Server

Benchmark yang dilakukan adalah mengirim HTTP request dengan concurency 500 dengan total request sebanyak 500,000.

  1. Benchmark PHP Swoole
# Pada Mesin Server
$ php hello.php
> Starting Swoole HTTP server...
# Pada Mesin Client (Load testing)
$ ab -c 500 -n 500000 http://<IP_SERVER>:8081/

2. Benchmark NodeJS

# Pada Mesin Server
$ node hello.js
> Starting Node HTTP server...
# Pada Mesin Client (Load testing)
$ ab -c 500 -n 500000 http://<IP_SERVER>:8082/

3. Benchmark Go

# Pada Mesin Server
$ go build hello.go
$ ./hello
> Starting Go HTTP server...
# Pada Mesin Client (Load testing)
$ ab -c 500 -n 500000 http://<IP_SERVER>:8083/

Hasil Benchmark PHP Swoole vs NodeJS vs Go

Hasil benchmark dibagi dalam tiga bagian. Satu adalah Request per Second (RPS). Kedua adalah Max CPU Usage atau penggunaan CPU maksimum. Ketiga adalah Memory Usage atau penggunaan memory.

Request Per Second

Penggunaan fungsi SWOOLE pada PHP

Request per Second (Semakin tinggi semakin baik)

Pemenang untuk benchmark request per second (RPS) adalah Go. Namun bersaing ketat dengan PHP Swoole.

  1. Go — 35,509 req/s
  2. PHP Swoole — 34,919 req/s
  3. NodeJS — 21,626 req/s

Max CPU Usage

Penggunaan fungsi SWOOLE pada PHP

Max CPU Usage (Semain rendah semakin baik)

Pemenang untuk benchmark Max CPU Usage adalah NodeJS dengan rata-rata 20% maksimum penggunaan CPU. Dimana penggunaannya tidak sampai separuh dari PHP Swoole dan Go.

  1. NodeJS — 20%
  2. PHP Swoole — 49,33%
  3. Go — 50,67%

Memory Usage

Penggunaan fungsi SWOOLE pada PHP

Memory Usage (Semakin rendah semakin baik)

Pemenang untuk penggunaan memory atau RAM adalah PHP Swoole. Dimana rata-rata maksimum penggunaannya 228,67 MB. Selish cukup kecil dengan Go diposisi kedua.

  1. PHP Swoole — 228,67 MB.
  2. Go — 232 MB.
  3. NodeJS — 266 MB.

Kesimpulan Benchmark

Untuk urusan performa PHP Swoole dan Go bersaing cukup ketat. NodeJS tertinggal cukup jauh untuk bagian ini.

Hal yang positif dari NodeJS adalah penggunaan CPU yang cukup rendah. Ini dikarenakan NodeJS secara design adalah single-threaded sehingga tidak memanfaatkan 8 core CPU yang ada.

Saya mencoba menjalankan NodeJS dengan mode cluster untuk multi-core processor menggunakan pm2. Namun anehnya performannya malah jauh menurun dari normal 21,626 req/s menjadi hanya 15k req/s. Entah apa yang salah dengan konfigurasi saya.

Hal yang diluar dugaan adalah Swoole yang fantastis dan hampir setara dengan Go. Jadi jika Anda dalah PHP developer dan tidak ada waktu untuk migrasi ke Go maka Swoole adalah alternatif yang sangat menarik.