PGO: Let It Go (PHP)

What if you could get a 7 to 8% boost in performance in your large PHP-based website without changing a line of source code? Let's take a look at how.

"We have met the enemy, and he is us." - Pogo, Walt Kelly

My dad was a big fan of the US comic strip "Pogo." He had a number of reprint books of Pogo strips which he shared with me, and I would read repeatedly. I think part of the fun for Dad was because he grew up in the Southeastern US, and Pogo would satirize the folks that live in the South.

Sometimes we programmers are our own worst enemies. 

We are taught in school how to understand operating systems, compilers, computer architecture, data structures and the like. We are taught to program using design, architecture, structure and precision. But we don't learn how to make it run fast.

We can hope that companies like Intel® will come along with a faster processor. (And this does tend to happen every year).  Or we can improve our compilers to produce better machine code. Or we can analyze our own code and change it to run more optimally.

For PHP, we do all three: We partner with the processor architects to improve the way they execute PHP; we look for changes we can make to the PHP code to run faster. But why not use the compiler to make the code faster?

This is exactly the PHP change we recently made. Just let the compiler do it. But today, you need to do your part.

The short answer is: use PGO when you compile PHP.

This uses a technique called Profile-Guided Optimization or PGO. The basic idea is as follows: When any program is compiled, the compiler uses some heuristics to determine the most likely path your program will take through the code, and optimizes the code using those assumptions.

PGO lets you train the compiler to produce a more optimized result. It does this by first compiling the code with instrumentation, then run the instrumented code which creates a profile. The final step is to recompile the program, using the profile to fine-tune the optimizations.

Amongst open source projects, very few use PGO. I know that Firefox builds by default with PGO, but I'm not sure of any others. We are introducing this with PHP and Python because it shows a measurable difference in complex customer workloads.

Here is the technique. First build PHP with instrumentation:

$ make prof-gen

This will create a binary of PHP which generates a profile. Now you need to run this version of php with some workload which is representative of the web site you are building. For example, you can use Wordpress if this is representative of the site you are running. Then, you need to recompile php using the profile you just generated, with

$ make prof-use

I just saw a demo of PGO with the new PHP 7 code that will be showing at the upcoming ZendCon conference. Build PHP using this technique creating the instrumentation, train it using WordPress, and then rebuild it using the profile which was just generated. Now use the optimized binary to run WordPress and compare it side-by-side with PHP built the default way. The PGO version gets 7 to 8% better throughput on average.

This seems so simple. Yet surprisingly, this optimization trick is used very little because you have to use PGO when you build PHP.

Try it. I'd be interested in your results.

Correction: an earlier version of this blog had the wrong procedure for using PGO with the current version of PHP. This version should work correctly. 

For more complete information about compiler optimizations, see our Optimization Notice.