Monday, June 16, 2014

Performance enhacements for Apache and PHP

In addition to updating and expanding the Bitnami Library, we are continuously looking for ways to improve our existing Bitnami stacks. In this latest round of updates, we focused on improving the performance of our Bitnami Stacks in limited resource systems such as Amazon EC2 micro instances, which have 1 virtual CPU and 613 MB of RAM, and Microsoft Azure extra-small virtual machines, that ship 1 CPU core and 768 MB of RAM.

We have now configured our Virtual Machines and Cloud Images to use the Apache Event MPM and PHP-FPM, resulting in reduced memory usage and an increase in the number of simultaneous requests that they can handle.

 

What is the Apache event MPM?

Apache supports three different Multi-Processing Modules (MPMs) that are responsible for binding to network ports on the machine, accepting requests and dispatching children to handle the requests.

- Prefork: Each child process handles one connection at a time. This is the default mode for Apache.
- Worker: Uses multiple child processes with many threads each.
- Event: This mode was designed to allow more requests to be served simultaneously by passing off some processing work to supporting threads and freeing up the main thread.

 

What is PHP-FPM?

PHP-FPM (FastCGI Process Manager) is an alternative PHP FastCGI implementation with some additional features useful for heavy-loaded sites. It has been bundled with PHP since version 5.3.3. PHP-FPM has the ability to start workers with different environments and to manage these processes.

 

Why are event MPM and PHP-FPM recommended for production?

The default configuration for Apache and PHP in Linux systems is to use the prefork MPM with an embedded PHP interpreter. This is a very robust configuration but it means that Apache needs to spawn a separate process for every simultaneous request it wants to serve. Because every child process loads a PHP interpreter and associated libraries, this configuration takes a significant amount of memory. In addition to this, a whole process is tied up when waiting for requests when browsers open a persistent connection to the server (which is particularly common with AJAX-heavy web applications.)

On high traffic websites, an alternate MPM (the event MPM) is preferable because it has the ability to serve a large amount of requests while maintaining low memory usage. It does so by using threads to serve requests. It retains some of the stability of a process-based server by keeping multiple processes available, each with many threads so a thread potentially misbehaving would only affect all the other threads in the same process.

Additionally, the event MPM uses a dedicated thread to deal with the kept-alive connections, and hands requests down to child threads only when a request has actually been made. That allows those threads to free back up immediately after the request is completed.

Because PHP is not thread-safe on Unix environments (in particular many of its most popular extensions), it is not possible to embed an interpreter in each event MPM process. It needs to live as a separate PHP-FPM process. Apache will serve all static resources (images, CSS, etc.) directly while PHP-FPM serves the PHP-related requests.

In the examples below, we provide some benchmarks. We used two different Amazon EC2 instances (micro and small) to run our tests. Both instances had the same WordPress installation and the same memory settings. We used the Siege tool, an HTTP load testing and benchmarking utility. We also used the webpagetest.org tool, which allows you to run speed tests from multiple locations using real browsers.

The test below uses the Siege tool to do a request to the WordPress web page and all the static files. We used 30 concurrent users for 1 minute and we got the following results:


Small EC2 instance with MPM prefork and "mod_php"
Used memory (Apache):        525MB
Transactions:        1606 hits
Availability:       89.92 %
Elapsed time:       59.08 secs
Data transferred:       12.49 MB
Response time:        0.89 secs
Transaction rate:       27.18 trans/sec
Throughput:        0.21 MB/sec
Concurrency:       24.28
Successful transactions:        1411
Failed transactions:         180
Longest transaction:        5.89
Shortest transaction:        0.11
Small EC2 instance with event MPM and PHP-FPM
Used memory (Apache+PHP-FPM):  278MB (max)
Transactions:        2480 hits
Availability:       91.75 %
Elapsed time:       59.10 secs
Data transferred:       21.30 MB
Response time:        0.69 secs
Transaction rate:       41.96 trans/sec
Throughput:        0.36 MB/sec
Concurrency:       29.11
Successful transactions:        2480
Failed transactions:         223
Longest transaction:        6.17
Shortest transaction:        0.11


The main differences when using PHP-FPM with the event MPM are the following:

- The used memory is much lower.
- The amount of data transferred is much higher.
- The transaction rate is higher and there are less failed transactions.

The next test shows the connection and page serving times for running 9 concurrent users using EC2 micro instances with the same WordPress sample site.

1. Apache MPM prefork with "mod_php"

Apache prefork MPM with "mod_php"


2. Apache event MPM with PHP-FPM
Apache event MPM with PHP-FPM


The main differences are the following:

- The load time is much lower in the second case. Note that the load time in the first case could be very different for different tests depending on the number of free child processes.
- The "time to first byte" for the requests is much lower in the second case.


In conclusion, the Apache event MPM increases the performance of Apache, allowing it to serve more requests with less memory. If you want to deploy a PHP application you should use PHP-FPM to handle PHP requests. This is highly recommend for running applications in servers with limited memory, such as like cloud instances with 512MB or 1Gb RAM. You can find more info about these tests on our Wiki and feel free to ask any questions in our community forum.

Want to try deploying a Bitnami application in the cloud? Select your favorite application at https://bitnami.com/stacks and launch it in minutes with just a few mouse clicks.

3 comments:

  1. Hi Beltrán,

    you are writing after the first table:
    "The transaction rate is higher and there are less failed transactions."
    I think the failed transactions are 20% higher with PHP-FPM. 223 to 180

    I don't unterstand why the webpagetest result for mod_php are so bad, there must be a problem. It's 10 times slower, all responses take a little more than 3 seconds, that does not make any sense. Couls you please run the test again, maybe 3 times, and take the average or so? That really looks like another problem, mod_php is not so much slower as you can see in the siege-tests.

    Thanks
    Michael

    ReplyDelete
  2. Hi Michael,

    Thanks for your comment. The issue is we ran 9 tests (9 independent browsers trying to access to the web page) at the same time. We configured Apache to have only 5 processes running (if you configure Apache to use more processes it is possible you ran out of memory in a micro instance). If you only have 5 Apache processes to serve all the content at the same time, some of the requests have to wait until one process is free, that is why it takes more time.

    If you run only one test for "mod_php", you probably get better results (it could be even faster than php-fpm) but Apache is serving only some requests, 13 in this example. If you increase the number of requests you can see how Apache with event MPM is faster than Apache prefork. I will be glad to try to reply more questions about this configuration at http://communtiy.bitnami.com Thanks!

    ReplyDelete