Breaking Boundaries with FastCGI - Andrew Carter

Breaking Boundaries with FastCGI

HTTP pipeline - as a restaurant

Client Customer
Server Restaurant
Request Order
Response Food
Application Chef
HTTP Daemon Waiter/Waitress

If PHP were a restaurant...

Customer enters restaurant
Waitress takes order
Waitress creates chef and gives order
Chef makes food
Waitress gives food to customer
Waitress brutally murders chef

The Proposal?

Don't kill the chef


What if our chef gets ill?

Solution #1

Kill the chefs before they have a chance to get ill

Solution #2

Use a better chef

What can cause our chef to get ill?

Memory Meltdown

Chef never forgets some of the meals they have made

Chef can only remember so much

Chef's head explodes

Remove references to unrequired objects


Chef forgets how to use oven after a couple of hours

Chef needs oven

ERROR 2006: MySQL server has gone away

Tantrum Handling

Chef encounters minor issue

Chef throws big tantrum

Distinguish between request errors and application errors

Let the application die if recovery is not possible

Evil Customer

Chef brainwashed by evil customer

Chef tricked into poisoning other customers

Think like an attacker

Avoid static and global memory

Chef Upgrade

Restaurant owner wants Chef with new recipes

Chef is pretty set in their ways

Restaurant owner forgets to kill old Chef

Chef keeps serving up old recipes

Remember to kill old Chef(s)

Leaving behind our restaurant...

CGI: Common Gateway Interface

CGI application must be executable by the web server

One instance of our application per request

HTTP request provided via environment variables

HTTP response written to standard output by application

Back in the day...

when I was 3

PHP was just a set of CGI binaries

We can still integrate PHP using CGI

We can also use native web server modules

We can also use PHP-FPM


PHP FastCGI Process manager


Like CGI... but faster

Making CGI Faster

Wrap our communication in a protocol

Implement this protocol over a socket connection

Keep our application alive between requests!


Keeps the PHP interpreter alive between requests using FastCGI

We are still killing our chef

Use FastCGI directly?

With a legacy application?

include 'lib/common.php';
include 'lib/database.php';

$escaped_url = mysql_real_escape_string($_SERVER['REQUEST_URI']);

$result = mysql_query(
    'SELECT html ' .
    'FROM pages ' .
    'WHERE url=\'' . $escaped_url . '\''

if (false === $result || !($page = mysql_fetch_assoc($result))) {
    header('HTTP/1.1 404 Not Found');
    $page = get_404_page();

echo $page['html'];

With Symfony?

use Symfony\Component\ClassLoader\ApcClassLoader;
use Symfony\Component\HttpFoundation\Request;

$loader = require_once __DIR__.'/../app/bootstrap.php.cache';

require_once __DIR__.'/../app/AppKernel.php';

$kernel = new AppKernel('prod', false);

$request = Request::createFromGlobals();
$response = $kernel->handle($request);
$kernel->terminate($request, $response);

The FastCGI protocol


Binary Protocol

                            pack() unpack()



Speedfony Bundle

composer require "phpfastcgi/speedfony-bundle:0.6.*"

// app/AppKernel.php

// ...
class AppKernel extends Kernel
  public function registerBundles()
    $bundles = array(
      // ...
      new PHPFastCGI\SpeedfonyBundle\PHPFastCGISpeedfonyBundle(),

    // ...
// ...

php app/console speedfony:run --env=prod
php app/console speedfony:run --env=prod --port=5000
php app/console speedfony:run --env=prod --port=5000 --host=localhost
php app/console speedfony:run --env=prod [--max-requests=200]

How much faster is this?

Benchmarking Application

500 page Symfony application

Single route which selects a random page from database

Renders using Twig

Clears entity repository after each request

Benchmarking System

VMWare Fusion - 2GB RAM - 4 cores (Intel Core i7, 3.4 GHz)

Ubuntu 64-bit Server 15.04

PHP 5.6.4


'ab', 50000 requests, concurrency level of 20

Control Test

OPcache enabled


First Test

6 worker processes

FastCGI protocol implemented in PHP userland

Second Test

6 worker processes

FastCGI protocol implemented by PHP extension

The Results

Results graph


PHPFastCGI is not yet production ready

No support yet for uploaded files

The Symfony kernel slowly leaks memory over multiple requests

Do you need PHPFastCGI?

Is your application fast enough already?

Why bother with the risk?

PHPFastCGI is a tool for high performance PHP applications


Well designed applications should not leak memory

Well designed applications should handle errors properly

PHPFastCGI is very easy to install

To Conclude

Consider long running processes when developing components and services

FastCGI is designed to allow applications to stay alive between requests

PHP is not designed to allow applications to stay alive between requests

That is possibly why no one has made a serious effort to do this

Used carefully, this can break performance boundaries

Thank you for listening

Any questions?