Benchmarking PHP performance with Server-Timing

This article describes how to use the Server-Timing APIAPI An API or Application Programming Interface is a software intermediary that allows programs to interact with each other and share data in limited, clearly defined ways. to benchmark server-side performance in WordPress.

What is the Server-Timing header?

The Server-Timing headerHeader The header of your site is typically the first thing people will experience. The masthead or header art located across the top of your page is part of the look and feel of your website. It can influence a visitor’s opinion about your content and you/ your organization’s brand. It may also look different on different screen sizes. is a standardized web technology for the server to communicate metrics to the client (e.g. the web browser). Such metrics are otherwise internal to the server and thus not exposed to the browser. They are exposed in a response header called “Server-Timing” which can contain one or more metric names, their values, and optional descriptions (see the header’s syntax documentation).

The concept is quite straightforward: some server-side code is used to measure something, e.g. the time a certain function takes to execute using microtime( true ) before and after the function execution and using the difference between both values. That value is then exposed as part of the “Server-Timing” header, for example like this:

Server-Timing: my-function;dur=8.2

Since the metric values do not come with units, it is critical that there is alignment in which unit is used for all metrics to expose. Since performance metric values can often be quite small, a good baseline is to use milliseconds. Let’s assume that that approach was used for the header above, so it means the function took 8.2 milliseconds to execute.

When a server response includes such a header, its values can easily be inspected on the client as well, as the browser provides functionality to parse the metrics in the header. For example, you can use the following command to see all metrics from the header formatted in a table:

console.table( performance.getEntries()[0].serverTiming )

Continuing the example of the above header, this would show a table containing just the “my-function” metric with a value of 8.2.

Your browser may also expose server timing metrics in a dedicated UIUI UI is an acronym for User Interface - the layout of the page the user interacts with. Think ‘how are they doing that’ and less about what they are doing.. For example when using Google Chrome, you can also see server timing metrics exposed in the Developer Tools’ “Network” tab, on the root document’s “Timing” tab.

The Network tab in Google Chrome, showing the Timing tab for the main document, which exposes server timing metrics
Server-Timing metrics shown in Google Chrome Developer Tools

Top ↑

Preparing a WordPress site for Server-Timing benchmarks

While there are many ways to send a Server-Timing header in a WordPress site using custom code, the Performance Lab plugin comes with a Server-Timing API built-in, which orchestrates the different metrics and their output in the header. Any other pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the Plugin Directory or can be cost-based plugin from a third-party or the theme on the WordPress site can use that API to register their own metrics to expose. This article will focus on using the Performance Lab’s Server-Timing API to send Server-Timing header metrics.

In order to prepare your environment for a benchmark, you first have to decide how you would like to make the comparison: the most reliable way is usually to use a single site for both test scenarios to compare, so that you can only change the single thing you want to compare performance for without risking other side effects or differences between the two test scenarios. For example, if you have your WordPress site in a local development environment, you could change the branch used to compare performance between one branch and another. Alternatively, if you want to compare performance between two WordPress versions, you could set up two separate sites, one with each WordPress version so that you don’t have to switch back and forth between them. If you go with that approach, make sure to pay precise attention to configure the sites in exactly the same way, e.g. the same PHPPHP PHP (recursive acronym for PHP: Hypertext Preprocessor) is a widely-used open source general-purpose scripting language that is especially suited for web development and can be embedded into HTML. version, the same kind of database, the same content, etc.

Follow these steps to prepare a WordPress site to perform a Server-Timing benchmark using the Performance Lab plugin:

  1. Install and activate the Performance Lab plugin.
  2. Go to the Settings > Performance screen, uncheck all module checkboxes and save. This ensures none of the Performance Lab’s other features are loaded, which could affect the performance of your actual comparison.
  3. Install and activate this one-liner plugin. It enables output buffering for the Performance Lab’s Server-Timing API, which is disabled by default, and by that allows the API to also record and send metrics that can only be measured after page output has started.
  4. (Optional, but recommended) Disable any debugging features of WordPress, e.g. set constants like WP_DEBUG, SCRIPT_DEBUG, SAVEQUERIES, to false.

After working through the steps above, your site should already send a “Server-Timing” header. You can verify this by using the JavaScriptJavaScript JavaScript or JS is an object-oriented computer programming language commonly used to create interactive effects within web browsers. WordPress makes extensive use of JS for a better user experience. While PHP is executed on the server, JS executes within a user’s browser. command from above in your browser’s developer tools console or rely on your browser’s Developer Tools, if the network panel surfaces Server-Timing data. At least the following three metrics, which Performance Lab exposes by default, should be included:

  • wp-before-template: Time it takes for WordPress to initialize, i.e. from the start of WordPress’s execution until it begins sending the template output to the client.
  • wp-template: Time it takes for WordPress to compute and render the template, which begins right after the above metric has been measured.
  • wp-total: Time it takes for the entire WordPress to respond entirely, i.e. this is simply the sum of wp-before-template + wp-template.

The latter two metrics are only exposed if output buffering is enabled, which is why it is crucial that you also performed step 3. in the list above.

Generally, try to make the environment as lean as possible so that it is focused on just the performance of what you are trying to compare. For example, if you want to compare WordPress coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. performance, don’t have any other plugins than the ones above activated. Or if you want to compare performance of a specific plugin, only have that plugin (plus the ones above) activated.

Top ↑

Using the benchmark-server-timing command

In order to benchmark specific metrics like the ones above, you could simply load the URLURL A specific web address of a website or web page on the Internet, such as a website’s URL you want to test in your browser, use the aforementioned JavaScript command or your browser’s Developer Tools to get the Server-Timing metrics, note them down, and then do the same for any other test scenarios. However, there is a major drawback of that approach: performance timings can vary greatly between individual test runs, so it is always advisable to perform multiple requests for both scenarios and use the median for each metric. This and other performance best practices are covered in more depth in the best practices article.

While this may seem reasonable to do manually for a few requests, the benchmark-server-timing command from the GoogleChromeLabs/wpp-research repository automates that process, so that you can do dozens or even hundreds of requests and get the median calculation. It is the recommended tool that the Core Performance Team has been primarily using for Server-Timing measurement.

In order to set up this tool for the first time, clone the GitHubGitHub GitHub is a website that offers online implementation of git repositories that can easily be shared, copied and modified by other developers. Public repositories are free to host, private repositories require a paid subscription. GitHub introduced the concept of the ‘pull request’ where code changes done in branches by contributors can be reviewed and discussed before being merged be the repository owner. repository to a directory on your machine and install the dependencies, e.g. with the following commands:

git clone $HOME/wpp-research
cd $HOME/wpp-research
npm install

Feel free to use any directory, the $HOME directory is just an example.

After that, you will have the tool ready to use. Here is a first example usage which makes 20 requests to the The community site where WordPress code is created and shared by the users. This is where you can download the source code for WordPress core, plugins and themes as well as the central location for community conversations and organization. home page. Inside your checkout of the GoogleChromeLabs/wpp-research repository, run the following command:

npm run research -- benchmark-server-timing -u -n 20

Note that this example will only result in a median response time being returned but no actual Server-Timing metrics. That is because is not configured to send a Server-Timing header. So keep in mind that it only makes sense to use the command with sites that send such a header.

Top ↑

Benchmarking server-side performance for a WordPress core pull request

The previous sections outlined the general considerations and setup needed to benchmark a WordPress site’s server-side performance using Server-Timing. This section will look at a more concrete use case to outline how you can use the aforementioned tools in practice.

A common workflow for members of the Core Performance Team is to benchmark the performance impact of an individual WordPress core pull request, which can help with several things:

  • Identify a potential regression before it would be committed to WordPress core.
  • Validate that an intentional performance enhancement actually results in an improved performance.
  • Measure how much a certain change impacts performance, e.g. to highlight it later if it brings a particularly high positive performance boost.

In order to benchmark server-side performance of the pull request, you need to compare how a WordPress site performs with the pull request applied versus how it performs without the pull request, e.g. the latest “trunk” branch. Therefore, it is advisable that you perform the benchmark using a single WordPress site, namely the one that you use as part of your WordPress core development environment. If you use WordPress core’s built-in development environment using Docker, it means you will need to rely on the site hosted at “http://localhost:8889”. Going forward, this section assumes that is the case. If you use another setup for your WordPress core development site, you can simply exchange the URL in the example code below.

You also need to decide which scenarios you want to test. A basic starting point is to test performance of the home page once using a blockBlock Block is the abstract term used to describe units of markup that, composed together, form the content or layout of a webpage using the WordPress editor. The idea combines concepts of what in the past may have achieved with shortcodes, custom HTML, and embed discovery into a single consistent API and user experience. theme, and another time using a classic theme. Given those two theming paradigms result in quite different behavior of WordPress core, it is important to test both scenarios. This will ensure any change that affects one type more than the other will be accounted for. When doing comparisons for both a block theme and a classic theme, you will need to run four benchmarks overall to compare the two scenarios:

  • Block theme active, using WordPress “trunk”
  • Block theme active, using the pull request branch
  • Classic theme active, using WordPress “trunk”
  • Classic theme active, using the pull request branch

The main objective is to compare the performance data of the two block theme scenarios with each other, as well as comparing the performance data of the two classic theme scenarios. Comparing performance between the block theme and classic theme scenarios is not necessary for this kind of benchmark, since we are not trying to measure whether WordPress has a faster server execution time with block themes or classic themes.

For every scenario that you want to test, go through the following steps to benchmark performance of a given WordPress core pull request:

  1. Make sure you have set up your WordPress core development siteDevelopment Site You can keep a copy of your live site in a separate environment. Maintaining a development site is a good practice that can let you make any changes and test them without affecting the live/production environment. following the 4 steps above, to ensure it sends a “Server-Timing” header.
  2. Update your local development environment to have the latest commit at the “trunk” branch.
  3. Check out the pull request’s branch locally at its latest commit.
  4. Ensure that the local pull request branch is also up to date with the same commit you have in your “trunk” branch, e.g. by merging “trunk” back into it via git merge trunk.
  5. Go back to your local “trunk” branch via git checkout trunk.
  6. Run the benchmark-server-timing command, e.g. in a separate tab, as follows: npm run research -- benchmark-server-timing -u http://localhost:8889 -n 100 -p
  7. Once it has completed and you see a table with all the metrics, change your WordPress core development environment back to the local pull request branch.
  8. Run the benchmark-server-timing command again in the same way as in step 6.
  9. Once it has completed, you now have two tables with benchmarking results that you can compare.

Below you see an example output from a single run of the benchmark-server-timing command. Note that your numbers will most likely be different.

║ URL                            │ http://localhost:8889 ║
║ Success Rate                   │ 100%                  ║
║ Response Time (p10)            │ 162.81                ║
║ Response Time (p25)            │ 166.5                 ║
║ Response Time (p50)            │ 169.66                ║
║ Response Time (p75)            │ 173.78                ║
║ Response Time (p90)            │ 178.46                ║
║ wp-before-template (p10)       │ 107.13                ║
║ wp-before-template (p25)       │ 109.65                ║
║ wp-before-template (p50)       │ 111.92                ║
║ wp-before-template (p75)       │ 115.88                ║
║ wp-before-template (p90)       │ 118.7                 ║
║ wp-template (p10)              │ 48.5                  ║
║ wp-template (p25)              │ 49.52                 ║
║ wp-template (p50)              │ 51.47                 ║
║ wp-template (p75)              │ 53.14                 ║
║ wp-template (p90)              │ 54.99                 ║
║ wp-total (p10)                 │ 157.04                ║
║ wp-total (p25)                 │ 160.59                ║
║ wp-total (p50)                 │ 163.73                ║
║ wp-total (p75)                 │ 168.13                ║
║ wp-total (p90)                 │ 172.07                ║

You may notice that the individual results actually include five numbers for each metric. That is due to the -p argument that you provided when running the command, which instructs it to include those more granular percentiles in the output. Having these percentiles helps assess the quality of your result, e.g. it allows you to determine how much variance there is between individual requests. Even if we primarily care about the medians (which is the same as the 50th percentile / p50), providing the medians in the data will provide more transparency to other contributors that may inspect those numbers later.

Now that you have all the results gathered, to make the comparison easy and to share the results with other community members, you could assemble them in a table somewhere, such as a public doc or spreadsheet. Here is an example that you could possibly use for inspiration, though the format you choose to share the results is entirely up to you. You can then share a link to it on the pull request or the associated TracTrac Trac is the place where contributors create issues for bugs or feature requests much like GitHub. ticket. It’s also a good idea to include a brief summary, at a minimum just mentioning the difference between the scenarios tested for the median wp-total metric, like for example in this Trac ticket comment.
Using the Server-Timing header allows you to expose server-side metrics in the WordPress response so that you can benchmark server-side performance granularly. Now that you know how to use the Performance Lab plugin to populate the Server-Timing header of your website, try using the benchmark-server-timing CLICLI Command Line Interface. Terminal (Bash) in Mac, Command Prompt in Windows, or WP-CLI for WordPress. command to run your own benchmark tests. For further reading, review the best practices article to better understand the various considerations to pay attention to when measuring performance.

Props @flixos90 @joemcgill @westonruter for contributing to this article.

Last updated: