WordPress Performance for Developers: Profiling websites with Xdebug

How to use Xdebug, a PHP extension, to profile website performance and find opportunities for optimization.

xdebug.jpg

Everyone knows that website performance - which basically boils down to speed - is incredibly important. It’s a major factor in the experience you offer users, it’s a big factor in SEO ranking, and it’s a mark of the attention and care that you put into your development work.

Where you can stand out from others is in how you understand and work on your sites’ performance. Multiple factors, from choices you make as developer to the hardware that your sites are hosted on - contribute to download speeds. All of them can make a positive or negative difference. You don’t need to be an expert in all areas, but you can set yourself apart in how you identify and work on each aspect of performance.

Looking deeper at the performance puzzle

For developers, that means broadening your outlook beyond the everyday concerns of optimising files and running a slick CMS. In this blog series, WordPress Performance for Developers, we’re taking a developer-friendly look at some aspects of performance that exists closer to the world of infrastructure and hosting than the world of design and dev. We’re digging into the parts of the tech stack that developers might not always think about, and showing how we measure and improve performance. 

Today it’s PHP debugging. While code optimization typically sits outside of your host’s responsibilities (we typically charge for our time when we do this sort of work), it’s not something that every web developer is comfortable doing for themselves. There's no reason why you can't take it on, though.

The tool we’ll use in this walkthrough is called Xdebug. It’s a PHP extension that you can easily use with Webslice Containers.

Does your website need profiling? One quick test

First things first - are you sure that there’s a performance issue to address? Do you know how serious it is, and how you’ll measure your improvement? The quick way that we answer these questions is by looking at the TTFB (Time to First Byte).

To quote Google’s web.dev introduction to TTFB:

Time to First Byte (TTFB) is a foundational metric for measuring connection setup time and web server responsiveness in both the lab and the field. It helps identify when a web server is too slow to respond to requests. In the case of navigation requests—that is, requests for an HTML document—it precedes every other meaningful loading performance metric.

As well as being very important, TTFB is a very easy metric to understand. It’s a number of seconds, and you can find your TTFB value with a simple curl request: 

curl -o /dev/null -H 'Cache-Control: no-cache' -s -w "Connect: %{time_connect} TTFB: %{time_starttransfer} Total time: %{time_total} \n" https://example.com

Google recommends that you aim for a TTFB of less than 0.8 seconds, but really anything above 0.5s is on the slower side. As a rule of thumb, that’s our threshold for getting to work on optimization.

We normally look at everything from a hosting point of view first - server speed, for example, whereas developers might start at the other end and inspect design elements or CMS plug-ins. As hosting nerds work up the stack and devs work down it, there’s a good chance that we’ll meet at the code.

So, while we’re here, let’s get to know Xdebug.

What is Xdebug? Why use it?

Xdebug is a powerful PHP extension designed to assist developers in debugging and profiling PHP code. It has a range of features that facilitate code analysis and optimization during the development process. With Xdebug, you can track and analyze variables, function calls, and script execution flow, making it easier to identify bugs, optimize performance, and improve overall code quality. 

Xdebug is invaluable for:

  • Debugging intricate code logic.

  • Fine-tuning code performance for speed and efficiency.

  • Identifying and resolving performance bottlenecks.

  • Gaining deep insights into code execution during development.

Insights you can get from Xdebug include:

  • Detailed breakdown of function calls and variable values.

  • Monitoring execution time and script performance.

How Xdebug and Webgrind work

Before we start analyzing data, we need to set up a few things. There are three main components:

  • Xdebug: Your debugging and profiling powerhouse for PHP.

  • Cachegrind: Profile data for analysis.

  • Webgrind: A user-friendly interface for visualising and interpreting Cachegrind reports.

See Profiling PHP websites with Xdebug in the Webslice Containers documentation to learn how to enable Xdebug and create a Webgrind dashboard.

Once Xdebug is enabled, cachegrind files are created every time you load a webpage. Because Xdebug is resource-intensive, it's best to run it in times when your live websites are quiet.

Interpreting your profiling results

Once you’ve successfully enabled Xdebug and generated your profiling data, it’s time to dive into the results. Webgrind provides a user-friendly interface for visualising and interpreting these results, making it easier to pinpoint areas for optimization. Here’s how to make sense of what you see in Webgrind.

webgrind-example.png
A simple Webgrind example, drawn from a website with only a phpinfo() page

Execution time: Uncovering performance bottlenecks

One of the primary metrics you'll encounter in Webgrind is execution time. As the name suggests, this metric tells you how long each function takes to execute. If you sort your results by execution time, you can quickly identify the most time-consuming functions in your application. These functions are prime candidates for optimization.

Obviously you’d expect some functions to take longer than others, so you need to use some judgement here. If you can cut 10% off a 0.1s time, that’s as good as halving the time a 0.02s function takes. 

Where you notice that a particular function is taking significantly longer to execute than expected, you can investigate further. You might find:

  • Inefficiencies in the code itself, in which case you can write your own fix.

  • Code that belongs to a particular plugin which is causing an incompatibility.

  • A nested loop that could be optimized. 

  • Opportunities to reduce the complexity of the algorithm being used.

Function calls: Reducing overhead

Webgrind also provides insights into the frequency and overhead of function calls. Functions that are called frequently or have a high overhead can significantly impact performance. For example, your application could be slowed down by a function that performs a database query multiple times within a loop.

In a similar way, functions that call external resources frequently (like an image hosted on a remote server) can also cause overhead if there is latency. It’s also generally not recommended to rely on those types of resources since their availability is not guaranteed.

By identifying these functions, you can look for ways to reduce the number of calls or optimize the function itself. This might involve caching the results of expensive operations, refactoring your code to reduce redundancy or ensuring the called upon resource is available on your server.

Keep profiling and keep learning

Profiling your website with Xdebug can uncover hidden performance bottlenecks and provide invaluable insights into your code’s behaviour. By systematically analyzing execution time, function calls, and call stack traces with tools like Webgrind, you can identify areas for optimization and make informed decisions to enhance your application’s performance.

Improving website performance is a continuous process. With Webslice Containers and Xdebug, you have a powerful ally in this journey. Whether you are a developer looking to fine-tune your code or a business owner aiming to provide a faster, more reliable experience for your users, Xdebug equips you with the data you need to make impactful improvements.

Keep reading