It’s finally happening. The end is near. The server is about to be destroyed by a fleet of Vogon cruisers. Actually, the server is about to be overrun by mouse clicks. It’s time to go look at your code and fix the slow bits.
The Internet is full of useful advice on how to speed up your code. There
are a lot of slide decks and articles focussed on pushing the last bit
of performance out of your code. They mention things like changing every
++$i, and even using
for instead of
foreach. Do these
optimizations help? Yes, but you are not going to notice it, unless they’re
in a tight loop with many iterations. It is also the wrong approach for
tackling performance issues. Before you can optimize, you need to find out
if your code is actually slow, then you need to understand the
code, and then you need to find out where it can be optimized.
Find out if it is slow
Before you should even consider optimizing, you should try to see how
slow your code actually is. Doing micro benchmarks for
++$i makes no sense if your app is fast already.
Instead, benchmark a full spectrum of URLs. This gives
you a good initial set of data to see which parts of your app are
actually slow, so you can spend effort on the places where it has the greatest
Understanding the code
Understanding the code isn’t always as simple as it sounds. If you’re the author of the code, than you are hopefully aware of how it is structured and how different parts interact. If you wrote it five years ago, maybe you don’t understand how it works so much anymore. (Depending on the code, perhaps even a week is too long ago to remember.)
There are a few tools that can help you to find out how your code flows
and how different parts interact. The first of the tools that I want to
introduce is inclued, a tool by
the maintainer of APC, Gopal Vijayaraghavan. It “allows you trace through
and dump the hierarchy of file inclusions and class inheritance at runtime.”
This means you can use it to show a graph of your include tree
and find out the relationships between the files. It will also tell you whether
a file referenced by
was actually included at that moment, or whether it has been referenced
before. It will also give you class inheritance dependencies.
In order to get a more detailed overview of what goes on in your code, you can use a feature of Xdebug called function traces. Function traces allow you to record every include, function, and method call, their result values, and variable assignments to a file on disk, in a few formats. By default, Xdebug only shows the name of functions and names of included files (to reduce the amount of information), but you can control exactly how much data will get dumped to the files with various settings.
Profiling your code
We have figured out which parts of the app are slow by benchmarking and have an understanding of how our code works by looking at traces. Now, the only thing that’s left is to find out which parts of the code make specific requests in the app slow. For that, there are a few tools.
A fairly high level tool is XHProf, written by the folks at Facebook, and subsequently open sourced. (It’s available in PECL.) It’s lightweight, so it can be used in a production environment. Here is a good overview on how to use it. The documentation is also helpful.
Another profiling tool is Xdebug. Xdebug’s profiling takes a different approach; it dumps a profile file to disk for either one request or for the duration of an Apache process. This profile file can then be read by various tools to analyze the profile information. KCacheGrind, a KDE app, is the most full-featured frontend to read profile files. It can be made to run on Windows and OS X. There is also a PHP app called Webgrind that allows you to interpret the profile files in your browser.
All of these tools will help you find bottlenecks in your code, and with the information about how the code is structured, you should be able to find optimization points.
This was a very quick overview of a few tools that help you to figure out if, how, and which parts of your app can benefit from optimizations. From now on, “whoosh!” won’t be the sound of your deadlines going past, but rather the sound of your app’s impressive speed!