PHP at Scale #4
Welcome to the fourth edition of PHP at Scale, I am diving deep into the principles, best practices, and practical lessons learned from the field of scaling PHP projects - not only performance-wise but also code quality and maintainability.
This month, I’ve decided to take a step in a different direction and focus on performance, more from a day-to-day perspective.
No worries, I know xkcd is right in the comic, so I will focus more on spotting performance issues, and ways of coping with it.
Top 5 hacks to fix slow web applications
This article is a bit old, but it will serve as an introduction. In general, I think you should not allow your product to reach a state when it’s struggling with the load, and you have no idea how to fix that quickly. In the linked article, I summarized some quick wins that should help you resolve the issue efficiently.
As we will cover how not to allow such cases later, let’s focus for a moment on the quick wins. If you have an approach that allows you to scale vertically or horizontally, you can take this as a first quick step.
Unfortunately, this does not always work. In a lot of cases we helped to fix, CPU and RAM were not the issue, but rather IO. IO is a bit tricky, as it can be a slow disk, but also network performance, wrong database transaction boundaries, etc.
Tools like Symfony Profiler (there are similar solutions for other frameworks too) allow you to quickly debug performance issues in your local development. They are very useful in some cases, especially to track the number of SQL queries performed for each request.
I did not find any nice articles on that, so I’m sharing the official docs, always a good point to start the research.
I would expect, most if not all of you already know it, but I would like to emphasize two things:
You can also use it to profile API and CLI flows. Profiles are stored even if the toolbar is not displayed, just open it in another tab and browse the list of requests. PHPStorm lists the requests too.
You should never use it in production.
Debugging and profiling PHP with XDebug
This article introduces XDebug. A tool I assume you are familiar with ;) Next to the debugging feature that most PHP developers use frequently, it also supports profiling options.
Of course, there is also XHProf, but let’s be honest: both tools are rather old, and not so user-friendly.
So what is the current go-to approach to profiling PHP apps?
Identifying bottlenecks with Blackfire IO
Blackfire IO is one of the tools we use to work with performance optimizations. It has significant pros when compared to the previously described methods.
The UI is way better, it allows profiling PHP on test, staging, and even production servers. It works well with CLI. Blackfire also allows for comparison of results pre- and post-optimizing so that you can see what has improved with your change.
The downside? It is a bit expensive. The development plan is enough in 99% of cases, making it €33.25/month, billed yearly. In our case, it was usually worth the money, even when it was used a couple of days a year. But we recently switched to a slightly different approach, described below. Before I mention it, let’s have a look at a case study of a very simple fix we did with the help of Blackfire:
Michal described how we fixed a very simple issue with performance, thanks to Blackfire. You could obviously also spot that issue in your local env using Symfony Profiler, but only if you had enough data in the DB. In other cases, it would probably take some time to spot this issue. Using Blackfire saved us an hour or two.
We had some more hidden performance issues that we were able to fix with the help of Blackfire for customers we consulted, but unfortunately, we can’t share them.
But are there better tools?
Using Application Performance Monitoring
Nowadays, using APM is in many cases the best option. It allows you not only to debug performance issues when you spot them, but it will actively monitor your service and notify you about potential problems. If an endpoint or view gets significantly slower/faster after a release, you will be notified about the detected anomaly. APM can also detect potentially problematic queries in your database. So you get the same data as in Blackfire, but you also don’t need to wait for your customers to complain about an issue, as the tool will let you know as soon as it happens.
Again, I don’t link any articles. Most of them are “sponsored” by some specific tools. We have used New Relic, Datadog and Sentry so far. All do the work, and they have slightly different approaches, so you can choose the one that works best for you.
PS. There are other tools, and also some open-source solutions. I checked the OS tools some time ago, and they were not as good as the paid ones.
I know, you might not use Apple computers, but I would like to bring a different point to the discussion with the article. On your performance optimization path, focus not only on production environment performance. Good performance for developers is also key. Optimizing local development environment speed is crucial. In his article, Krzysiek shows how an upgrade of his laptop and switching to a different Docker set-up improved the build times from 60s to 7s. That’s almost a 10x improvement!
The same rule applies to optimizing all development-related processes: automated tests, CI/CD pipelines, etc.
Closing thoughts
I was a bit surprised when I worked on the content research for this release. For some reason, there are not many quality articles on performance tuning/optimization, and those that exist are… well, let’s say not ideal. I missed a good article on almost any approach described above, and case studies like the one from our blog are nice but very case-specific. Articles about Blackfire or New Relic are mainly written by themselves, or related parties. I think we need to write some of our own. In case you know such articles, or would like me to focus on some specific topic, let me know!
PS. Don’t fall into the trap of silly optimizations. Lots of articles suggest changes from print to echo, this is something that does not matter nowadays.
Why is this newsletter for me?
If you are passionate about well-crafted software products and despise poor software design, this newsletter is for you! With a focus on mature PHP usage, best practices, and effective tools, you'll gain valuable insights and techniques to enhance your PHP projects and keep your skills up to date.
I hope this edition of PHP at Scale is informative and inspiring. I aim to provide the tools and knowledge you need to excel in your PHP development journey. As always, I welcome your feedback and suggestions for future topics. Stay tuned for more insights, tips, and best practices in our upcoming issues.
May thy software be mature!