Stop using PHP-FPM to argue using Nginx vs Apache

I often see “Apache vs Nginx” discussions appearing on reddit and some of the arguments people make are plain ridiculous. So now I want to address one that makes my eyes roll the post: PHP-FPM.

When Nginx first came into PHP world its popularity was mostly fueled by numerous benchmarks showcasing its speed vs a LAMP setup. You see Nginx didn’t have anything like Apaches’ mod_php and required the use of PHP-FPM, which indeed was a much faster way of processing PHP on multicore systems. The mistake people often did was to compare those setups and conclude that Nginx was just a better HTTP server.

Nginx is a great webserver, and its default setup is designed for performance, while the default Apache setup provides much more in terms of flexibility. But please don’t say that Nginx is better just because PHP-FPM is faster than mod_php, when you can easily setup Apache to use FPM too

One of the contributing reasons is that there is so many different configuration options in Apache that a person can easily misconfigure it. Apache has 3 MPMs: prefork, worker and event and even proxying request to the PHP-FPM server can be done in at least 3 entirely different ways. Nginx is easier to set up if you’re looking for a “good enough” solution, it’ll run pretty good out of the box.

At that time I thought people would eventually understand the actual difference and judge webservers on their own merits, but years passed and it’s still happening! So pretty much now we have 4 categories of developers:

  • People that use Apache because it comes with windows packages like WAMP and is very easy to setup on any Linux distro. These people don’t care how their PHP is executed at all
  • People that read a blog post that Apache isn’t cool anymore, installed Nginx with PHP-FPM and consider the first group to be inferior and less tech savvy.
  • People that are supporting a legacy app, are stuck with an old version of Apache ( maybe 1.3 even ), and think moving to Nginx would boost their performance sky-high
  • And there obviously is a portion of developers that actually have experience in both and can select the one that fits the task the best

The problem is that most of the “Apache vs Nginx comparison” posts are written by the first 3 groups of people. The fourth group has long ago realized that there is enough info on the internet to stop talking about it over and over.

The lessons you should take from this post are:

  • Try running Apache 2.4 with mpm_event and PHP-FPM using ProxyPass and see the results you get
  • If you have only a single core PHP-FPM won’t be faster than mod_php ( it’ll take a separate blog post to explain why )
  • In tech, never pick a single side, stay flexible
  • If you need performance use HHVM

Developer title inflation

The laws of Economics apply to all kinds of human relations and it’s principles can be easily extrapolated to explain a great number of things, including developer titles. This is a joke I heard some time ago:

– How can a Junior developer become a Senior one?
– Simple. Just change the job twice

Sad, but true, and there are a great number of things that contribute to this.

Demand-pull inflation
The friendly HR girl that handles the hiring process often has only a vague idea on who she is actually looking for. She’s been given a checklist by the CTO and wants to do her job well by finding someone fitting as fast as possible. Why not let a guy with 2 years of experience a chance for the Senior dev vacancy? Especially if she represents a small agency that doesn’t get that many applicants in the first place.

The CTO may decide that even though the person he just interviewed isn’t quite the Senior they’re looking for he still could hire him for 80% of the salary, but the title stays. Titles, unlike money, cost the company nothing.

People conducting the interview use themselves as a standard
If the developers conducting the interview aren’t very good themselves, they are likely to also overestimate the interviewee. In fact they will do everything not to hire a person who is more knowledgeable than themselves, so that not to shake their position of power.

It’s getting very easy to develop
We have a multitude of libraries and frameworks available today. Becoming “good-enough” to string those together and make a CRUD app is no challenge at all. This combined with that a lot of people consider a developer that can throw together a website on his own a mid-level already means that the Junior title is pretty much skipped entirely, and people rarely consider themselves Junior PHP devs for longer than half a year.

Titles don’t get revoked
This is the worse kind of inflation to me. This happens when people who were genuinely awesome 4 years ago stopped learning new stuff, stick to old practices and put ‘hipster’ label on everything new. In PHP those are the kind of people who think namespaces suck, Composer is complicated and testing is just wasting time. They proudly state their 10+ years of experience, while actually being harmful to the team. Truth be told, their experience does come in handy when it comes to architecture sometimes. But development is so rapidly evolving that if you miss just 2 years you’re probably far behind the bandwagon.

Titles are rarely specific
Being a “Senior WordPress developer” doesn’t make you a “Senior PHP developer”, and somewhat vice versa actually.

The terrible consequences
There was a discussion on reddit recently that discussed questions that should be asked when interviewing a Senior developer. I was surprised at how trivial those were. “Knowing weak and strong points” of current ORMs is something a mid-level dev should be easily able to do. What happened to knowing algorithms, data structures, patterns, extensive database knowledge, cryptography etc. What do you call a person who knows all that then ?. You can’t put those on the same spot as the guy who can choose between ORMs. Perhaps we need more titles, maybe we need to start calling ourselves “exalted PHP developers of the 5th rank” from now on. But the worst part is that people who already consider themselves to be Senior stop learning, and a person who doesn’t learn constantly will never notice how ignorant he in fact is. And one day on your first day in a new company you may find out that you will now be lead by people much less experienced than you, and every architectural decision is going to be a battle between your knowledge vs their ignorance. And that frankly sucks.

TL;DR Be modest and learn every day.

A checklist for framework developers

So, there have been some new frameworks being posted on reddit, with the expected result of receiving a lot of hate and criticism. I can kind of understand both sides here, since just about a year ago I’ve seen similar responses towards my PHPixie. Since then the flames calmed down and it has now a considerable userbase with 386 installs in the last 30 days. The important part here is to be able to take in constructive criticism and carry on making your project better. I’ve learned a few things the hard way as I went, and I’d like to share them with other people willing to release their brainchild to the world.

  • Tests – you must have those to be taken seriously. Even if it’s the first version, alpha or anything. The tests are the first indicator that you are putting real effort in
  • Find a niche – There has to be something about your framework that makes it stand out, and you have to focus on it. I really pushed a lot of effort behind the “great performance” argument. I also submitted it to Techempower Framework Benchmark Suite to prove it. Don’t ever state something while not having anything to back it up with
  • Read a book – there should be no singletons, god objects, shared state or anything like that in a modern app
  • Write docs – That includes writing docblocks, generating an API documentation from those docblocks, writing some tutorials and a nice about page.
  • Be prepared to compare it to existing frameworks – there has to be something better with your approach. If there isn’t don’t bother releasing it.
  • Use PSR-2 – I made the mistake of writing PHPixie in the style I liked and then had to rewrite it. The style must suite the majority, not just you. You’re not making it for yourself
  • Don’t expect any help or pull requests from the very start
  • Support your users as much as possible, at least install some forums script to be able to talk to them
  • Buy a domain and spend some time on site design. Make it look legit
  • Commit frequently – Your Github history has to indicate your project is not dead
  • Participate in the community – You can’t expect people to help you with your project if you ignore theirs
  • Don’t give up

If this sounds like too much work, just pick a smaller project. It’s better to make a smaller masterpiece than a big ball of mud.

PHP memory leaks and garbage collection

Historically memory leaks have not been a huge concern for PHP development. Since PHP processes exit after processing a request all used memory is deallocated. But that doesn’t mean we are free to not care about memory management altogether. If your application is processing several requests at the sime time, the total amount of wasted memory may add up to a hefty number.

With projects like ReactPHP become more popular and widely used PHP is entering the domain of permanently running processes and we all look forward to using those to speed up our applications. But for that to become a reality our applications and frameworks have to be carefully rewritten to prevent memory leaks, since even the smallest one can grow to eat all available memory in a span of a month.

PHP utilizes reference counting to decide when a object can be removed. Eachtime you assign an object to a new variable its refcount is increased by one


$a = new stdClass;
$c = $b = $a;
xdebug_debug_zval('a'); //refcount = 3
unset($b, $c);
xdebug_debug_zval('a'); //refcount = 1

When a refcount reaches 0 the memory is deallocated. This is the first thing you have to think about when instantiating multiple objects, e.g. your domain entities. You have to make sure that the references to them don’t hang around after they are no longer needed. One good rule of thumb for doing so is avoiding global state as much as possible. If all your object references are inside some local scope, it’s much easier to keep track on whats happening to them than when they are scattered all over the place.

Now let’s see wht happens here:


$a = new stdClass;
$b = new stdClass;

$a->b = $b;
$b->a = $a;

xdebug_debug_zval('a'); //refcount = 2
xdebug_debug_zval('b'); //refcount = 2

unset($a, $b);

After we unset both $a and $b variables we have no way of accessing those objects from our application anymore, but their refcount is not 0. Since what was $a still references $b and vice versa both their refcounts are 1, and they won’t be removed from memory. And that is what a memory leak is. In a perfect world we would try to avoid this as much as possible, but this might be hard to achieve. PHP tries to detect such unreachable objects using it’s garbage collector. When it’s called it looks through the memory for lopps in object references and deallocates them, thus saving us memory. But this process is not free, running it too often may slow down the execution time. The PHP manual states the impact is about 7% which is quite considerable.

I have found a nice trick that works for me to both have gc collection and get an almost insignificant performance impact: to run the garbage collection only after the end of each request. You can do it like so:


gc_enable();
gc_collect_cycles();
gc_disable();

Basically we are enabling garbage collection, running it once and disabling it again. This way we ensure that it runs only a single time per request.