Skip to content

Performance Comparisons

Charles R. Portwood II edited this page Aug 23, 2020 · 5 revisions

TL;DR; Yii2-PSR7-Bridge with RoadRunner as the task-runner can process almost 2x as many requests as an optimized Nginx/FPM configuration with a smaller shortest and longest transaction time. Compare 2255.99 transactions/s to 855.55 t/s.

Since RoadRunner is limited strictly by the number of cores on your server (and since you can eliminate several redundant processes), this library has the potential to increase single server performance dramatically and reduce server costs.


Metrics for this page are derived from a 60s, 25 concurrent user siege test against a Yii2 applications. The siege command used is as follows:

siege -c25 -t60S --no-parser http://127.0.0.1:8080

Note that these are point-in-time results. Your results may differ. This page exists to illustrate the potential speedup between default implementations and a PSR7 task runner.

Yii2 App Basic

Yii2 App Basic was last tested against Yii2 App Basic 2.0.14.

Yii2 App Basic with built in PHP Server

Results are derived against the php built in server ./yii serve.

Data

Label Data
Transactions 14964 hits
Availability 100.00 %
Elapsed time 59.18 secs
Data transferred 389.69 MB
Response time 0.10 secs
Transaction rate 252.86 trans/sec
Throughput 6.58 MB/sec
Concurrency 24.97
Successful transactions 14964
Failed transactions 0
Longest transaction 0.20
Shortest transaction 0.09

Technical Notes

  • ./yii serve also serves assets from the web/assets folder, so the raw data transferred would be higher. Throughput is also expected to be higher.

Yii2 App Basic + Nginx + PHP-FPM

Results were derived against Nginx 1.15 and PHP 7.2 docker images:

Dockerfile:

version: "3.6"
services:
  nginx:
    image: registry.pkiapps.com/punchkick/nginx:mainline
    ports:
      - "8080:80"
    links:
      - php:php
    volumes:
      - ${PWD-.}:/var/www
      - ${PWD-.}/config/.docker/nginx/conf.d:/etc/nginx/conf/conf.d:ro
    networks:
      main:
        aliases:
          - nginx
  php:
    image: registry.pkiapps.com/punchkick/php:7.2-alpine
    working_dir: /var/www
    volumes:
      - ${PWD-.}:/var/www
    networks:
      main:
        aliases:
          - php

networks:
  main:

nginx.conf

worker_processes 1;
pid /var/run/nginx.pid;

events {
    use epoll;
}

http {
    include mime.types.default;
    server {
        listen 80 default deferred;

        server_name _;

        root /var/www/web;
        index index.php;

        location = /favicon.ico {
            log_not_found off;
            access_log off;
        }

        location = /robots.txt {
            allow all;
            log_not_found off;
            access_log off;
        }

        location / {
            root /var/www/web;
            try_files $uri $uri/ /index.php$is_args$args;
        }

        location /index.php {
            internal;
            root /var/www/web;
            include fastcgi.conf;
            fastcgi_intercept_errors on;
            fastcgi_pass php:9072;
            include fastcgi_params;
            fastcgi_read_timeout 3600s;
        }
    }

    upstream php72 {
        server 127.0.0.1:9072;
    }
}

Data

1 Worker Process
Label Data
Transactions 50200 hits
Availability 100.00 %
Elapsed time 59.07 secs
Data transferred 188.72 MB
Response time 0.03 secs
Transaction rate 849.84 trans/sec
Throughput 3.19 MB/sec
Concurrency 24.96
Successful transactions 50200
Failed transactions 0
Longest transaction 0.18
Shortest transaction 0.01
4 Worker Processes (Normal Nginx Optimizations)
Label Data
Transactions 51196 hits
Availability 100.00 %
Elapsed time 59.84 secs
Data transferred 192.47 MB
Response time 0.03 secs
Transaction rate 855.55 trans/sec
Throughput 3.22 MB/sec
Concurrency 24.96
Successful transactions 51196
Failed transactions 0
Longest transaction 0.19
Shortest transaction 0.01

Yii2 App Basic + PSR7 Bridge + RoadRunner

rpc:
  enable: true

http:
  address: 0.0.0.0:8081
  workers:
    command: "./../roadrunner"
    pool:
      numWorkers: 1
      #maxJobs: 1

The roadrunner script used is shown as follows:

#!/usr/bin/env php
<?php

ini_set('display_errors', 'stderr');
require_once __DIR__ . '/../vendor/autoload.php';

$relay = new Spiral\Goridge\StreamRelay(STDIN, STDOUT);
$psr7 = new Spiral\RoadRunner\PSR7Client(new Spiral\RoadRunner\Worker($relay));

defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'dev');

$config = require_once __DIR__ . '/bootstrap.php';

while ($request = $psr7->acceptRequest()) {
    try {
        $application = (new \yii\Psr7\web\Application($config, $request));
        $psr7->respond($application->handlePsr7Request());
        unset($application);
        gc_collect_cycles();
    } catch (\Throwable $e) {
        $psr7->getWorker()->error((string)$e);
    }
}

Data

Single worker process

Results were derived against a RoadRunner instance with a single persistent worker.

Label Data
Transactions 43497 hits
Availability 99.77 %
Elapsed time 59.13 secs
Data transferred 164.50 MB
Response time 0.03 secs
Transaction rate 735.62 trans/sec
Throughput 2.78 MB/sec
Concurrency 24.98
Successful transactions 43497
Failed transactions 99
Longest transaction 0.16
Shortest transaction 0.02

4 worker process

The workload listed here is more comparable to the Docker Nginx/FPM configuration.

Label Data
Transactions 133126 hits
Availability 99.77 %
Elapsed time 59.01 secs
Data transferred 503.47 MB
Response time 0.01 secs
Transaction rate 2255.99 trans/sec
Throughput 8.53 MB/sec
Concurrency 24.91
Successful transactions 133126
Failed transactions 302
Longest transaction 0.17
Shortest transaction 0.00

Technical Notes

  • The failure rate only shows up in siege tests. Normal browsing doesn't trigger the error at the same frequency.
  • Throughput and Data transferred rates will be lower since go's built in web server is handling static assets in web/assets and web/css.
  • Compared to the built in PHP server:
    • Single worker process has a 190% improvement from PHP's built in server
  • Compared to Nginx:
    • A single worker Nginx process with a full FPM pool is 15% more performant than a single go worker process.
    • In comparison to a 4 worker Nginx process, 4 roadrunner workers have a 160% advantage over an optimized Nginx configuration. Compare 133126 roadrunner transactions vs 51196 nginx transactions.