Profiling a WordPress site (…or how we shaved almost a second off server response time)

Published on by Ivan Švaljek
Code profiling is a process of measuring time and resources taken by a particular codepath. In this article we’ll focus on frequency and duration of function calls in a single page load. I’m using XAMPP on Windows, but this guide can be used on any LAMP stack. Php profiling is done using xdebug, a php extension that […]
cachegrind

Code profiling is a process of measuring time and resources taken by a particular codepath. In this article we’ll focus on frequency and duration of function calls in a single page load.

I’m using XAMPP on Windows, but this guide can be used on any LAMP stack.

Php profiling is done using xdebug, a php extension that provides step debugging and profiling for php apps. For this we need to edit the php.ini file located in your LAMP stack’s php folder, in my case C:\xampp\php\php.ini, and add/replace these php directives:

The topic of this article is xdebug profiling so I won’t get into step debugging directives, but if you wish to test it out just change the line xdebug.remote_enable = 0 to xdebug.remote_enable = 1.
The profiler directive xdebug.profiler_enable_trigger = 1 allows us to control when the profiling will actually happen. Running with the profiler always on would slow down your development cycle quite a bit, so we enable this xdebug directive and use a GET or POST parameter XDEBUG_PROFILE on the page we want the profiler to run. For example: http://localhost/example-site/?XDEBUG_PROFILE. When we open such an url, the profiler will collect all the function data and store the output in a file defined by these directives:

The output is a cachegrind text file that can be visulized by a cachegrind compatible program. I use QCacheGrind on Windows, but there are alternatives for all major platforms.
This is how the output file looks like when visualized in QCacheGrind:

cachegring-unoptimized

What immediately caught my eye is that the get_field line took almost half the processing time of the homepage load. So I looked into front-page.php and found that there were only 13 lines with ACF get_field() function calls. Some of them were simple text fields that could be replaced 1:1 by get_post_meta(), and some were image and gallery fields, but replacing them was also no biggy.

 This is how the cachegrind file looks like after these quick optimizations are made (notice the total time count in this and the previous screenshot):

cachegring-optimized

Finally, I placed the optimized and unoptimized code paths in a separate include files, and made the GET parameter switch to choose which one loads on the homepage. This is the bash script that uses curl to measure server response time and outputs a csv text (replace example.com with your actual domain):

This is the end result, time it takes the server to output the first byte, reduced from 2100ms to 1188ms (on average):

Screenshot from 2016-04-09

There is still a lot of room for improvement, but for a 45 min optimization run, this is pretty sweet result 🙂 

About the author

Leave a Reply

Your email address will not be published. Required fields are marked *