Updated on December 6, 2019
For a long time, I made all my side projects with a custom-built PHP framework (or rather a set of libraries). At the beginning of my PHP journey (in 2011), writing these libraries was a good exercise in learning the language.Recently, though, I started to run into all kinds of limitations:
The only frameworks I worked with before were Zend Framework 1 and Symfony 5.
With my previous project, I had a first-hand experience of running a relatively high load web site. The highest traffic level I saw was 10 million page views a day and up to 10,000 concurrent sessions. At the backend, we had 7 web nodes serving PHP requests (Linux, Nginx+php-fpm, MySQL, MongoDB, PHP7, Memcache). And being stuck with Zend Framework 1 was not fun :)
The other one, Symfony 5, I tried for a small project for a month and left it with a feeling of too much magic happening behind the scene for my taste. And the learning curve was pretty steep.
So I decided to take a look at the current scene of PHP frameworks to get the feel of everyone and test the performance (in case I would be lucky enough to get high traffic again).
Here is the list I chose what to test from.
I want to answer the following questions:
How many simple HTTP-requests can a framework consistently serve on a comparatively cheap Digital Ocean droplet (40$, dedicated CPU, 2 cores, 4Gb of memory)?
|Slim (skeleton) 4.3.0||1,161||100,347,840||80|
|Zend (skeleton) 3.1.13||108||9,365,760||87|
Testing PHP frameworks is complicated because there is much ground to cover: template engines, ORMs, caching... For now, I am choosing to test a simple “Hello world!” response with PHP. I’m assuming it is an ideal setup for testing performance overhead of various frameworks - a way to test the cost of a framework “takeoff.”
I’m interested in how many HTTP-requests a framework can consistently serve:
An unintuitive fact about frameworks is that every one of them can serve a roughly equal number of requests with roughly the same latency.
Let me repeat that: in an ideal world, with an infinite amount of computing resources, all frameworks perform almost equally.
It is not that one framework is inherently slower than the other. Some frameworks are slower just because they consume more CPU or more memory or make more reads from a disk or a database.
From my experience with high-traffic websites, when we deal with running php-fpm+Nginx, it is usually CPU we should be worried about, not memory. If we take an example configuration of 1 CPU core and 4GB of memory, php-fpm+Nginx can easily consume 100% CPU with less than 5% of memory usage.
That is why I choose a 40$ Digital Ocean droplet: it is the cheapest one with a dedicated, not shared CPU.
In real life, we do not want to max out or CPUs. It leads to an increase in server response time (latency), which is terrible. And it does not leave us any headroom for traffic spikes, which is wrong. Usually, for production web-nodes, it is a good idea to stay well below 50% of CPU limit.
For this test, I decided to limit PHP usage on the “Web” server to 50%.
I do not imply that frameworks that perform slower are worse:
Laravel is the only framework, which was ridiculously slow and error-prone out of the box. I could not get it to serve even 10 requests per second without multiple timeout errors and latency instantly spiking over 100 ms.
Then I looked at the slow log and discovered that Laravel had some troubles with sessions handling (of course, session folders had all the necessary rights and user/group assigned to them).
After changing config values for SESSION_DRIVER from “file” to “array,” Laravel performance increased 10x.
Maybe I missed something important there, so please let me know if that is the case.
Phalcon is a beast. It is the only framework that comes as Zephir/C extension. And in some cases, it is faster than plain PHP.