iRepair Media — homeiRepairMedia

Performance

Why a speed score and real-world speed disagree

A performance report puts two sorts of number side by side: a controlled test on borrowed hardware, and a trailing record of real page loads. They are not the same measurement and they disagree by design. Here is how to read both, and how to narrow a slow site down to a cause before anybody quotes you for fixing it.

13 min readiRepair Media

Two numbers, two different questions

Lab data and field data sit on the same screen, carry the same metric names, and look comparable. They are not measuring the same thing.

Lab data is one simulated load. A machine fetches your page with an empty cache, on a deliberately slowed processor and a deliberately slowed connection, from wherever that machine happens to sit. Its value is precisely that the conditions are held still: change something on the page, run it again, and the difference you see is attributable to your change rather than to the conditions.

Field data is not a test. It is history — a trailing window of real page loads, reported by the browser as they happened. Whose loads matters, because this is where the panel gets over-read. The public field dataset is contributed by Chrome users who have opted in to reporting their usage, on page loads that meet its eligibility rules. Safari and Firefox do not appear in it, and nor does anyone who declined. If much of your audience is on iPhones, that panel describes a slice of your traffic rather than all of it. Monitoring installed on the site itself is a second field source, and it runs in every browser that visits — though the measurements themselves are not all available everywhere, so what it recovers from an iPhone is narrower than what it records from Chrome.

Two consequences follow from that, and they are worth separating. Because field data covers a trailing window, it moves slowly: deploy a fix this morning and the figures keep including everybody who arrived before you deployed, until the window has rolled past them. And because a lab result is a single sample on a shared machine, it wobbles — run the same URL three times and you will get three answers. A lab run is a reading, not a fact.

On a site with light traffic there may be no field data for the page at all, or only a figure for the whole origin. That is not a fault, just too few qualifying loads to summarise. It leaves the simulated run as your only measurement, which is worth knowing before you treat it as evidence about your customers.

When the two disagree, neither is wrong. The disagreement is information about how your visitors differ from the simulation, and four of those differences are worth checking directly.

  • Device and network. The simulation fixes both; your audience does not. Your own analytics answers this, in the device breakdown and the acquisition report. The gap widens with the amount of work the page asks of the processor, because an older handset executes the same script more slowly.
  • Cache state. The lab always arrives as a first-time visitor. A site with a high proportion of returning visitors reads better in the field than in the lab, because those visitors re-use scripts, stylesheets and images already on their device. New against returning is in your analytics too.
  • Distance. A test run near your server flatters you. The cost is per round trip rather than per file, since one connection carries many requests, so it hurts most where requests are serialised — a stylesheet importing another stylesheet, a script inserting an image, a redirect chain before the page is even reached.
  • Page mix. A single-URL lab result and a site-wide field figure are not the same subject. The site-wide figure is weighted towards whichever pages get the traffic, so testing your homepage against it compares your best-maintained page with an average of everything else you own.

Those four also settle the two awkward cases, with one addition on each side. A simulation stops at the load, so slowness that only arrives when somebody taps is invisible to it. And a test run never scrolls. Layout shift is only counted where it is visible, so anything that moves as a visitor works down the page — an image arriving with no space reserved for it — is measured for real people and missed entirely by the simulation.

The score is a summary, not a measurement

A performance score is a weighted blend of several lab metrics — among them how soon anything appears at all, how soon the largest thing appears, how long the main thread was blocked during the load, and how much the layout moved while it happened. Blending has a consequence people skip past. Two pages with the same score can be failing entirely different metrics, and the total can move without a single thing a visitor would notice having changed. The number is a convenient headline. It is not a quantity anybody experiences.

The field side is reported differently again. Each metric is a percentile across the window — the figure quoted is the experience at the 75th percentile of page loads, not the average — with a pass, needs-improvement or poor band attached, and the distribution behind it where the report shows one. So improving the worst tail of visits can leave the quoted figure exactly where it was, because that figure is one point in a distribution rather than a total. And if you track progress by the colour of the band, a real improvement inside a band looks like nothing happened while a small one that crosses a boundary looks like a step change. Read the value and the distribution, not the badge.

This is also why chasing the total goes wrong. The lab metrics are computed over the load, so work moved outside that period stops being counted while the person doing it waits exactly as long: defer script execution until after the first interaction and the report improves, because the wait has moved to the moment somebody taps. The other familiar case is lazy loading applied to every image, including the largest one at the top of the page. With the native attribute no script is involved — the browser holds that request back until it has done enough layout to establish the image is wanted, rather than starting it as soon as the markup is parsed. An older JavaScript lazy-loader is worse, because the real source sits in a data attribute and nothing can be fetched until the loader has run.

The useful goal is narrower than a score: name the metric that is failing, on the template that matters commercially, for the visitors it is failing for, and then find the cause of that. A site can be worth fixing on one template and entirely fine on the rest, and a blended total will never tell you which you have.

The order to diagnose in, and why the order matters

Audit tools list their findings by category. The categories are not independent of one another, so working through them in the order they were printed means measuring each step through the delay caused by the step above it. The dependency order is short.

First, time to first byte — how long from starting the navigation to the first byte of HTML arriving, which covers any redirects, the DNS lookup, the connection and the server's own thinking time. Everything downstream inherits it, so while it is late you cannot tell whether a stylesheet is slow or merely waiting its turn, and any improvement you make further down is too small to see against it. It is the step people skip, because it is the least visual.

Second, what blocks the first paint. A stylesheet in the head is not executed, it is parsed, and the browser holds off painting until it has the rules — painting first would mean redrawing the page in different clothes a moment later. A stylesheet scoped to another medium, print for instance, holds nothing up. A synchronous script is stricter: it stops the parser where it sits, so nothing below it is added to the page or run until that script has been fetched and executed, and it will not run until any stylesheet already requested has arrived. The browser does read ahead to start downloading what it can see coming, so those files are usually already in flight — what waits is the page being built, not the fetching. Content above it can and does paint, which is the useful diagnostic. If the top of the page appears and the rest lands in a lump afterwards, look at what sits between them.

Third, the largest contentful element. Find out what it actually is before deciding why it is late, because it may well not be what you assumed — a background image set in CSS, a video poster frame, or a block of heading text. Then ask which kind of late it is. Discovered late, because it is referenced from a stylesheet or inserted by a script and so is invisible to the browser's preload scanner. Delivered late, because the file is larger than the space it is displayed in. Or painted late, because the text is waiting on a web font before it can be drawn.

Fourth, layout shift. It comes fourth because some of it is a symptom of arrival order, and fixing the order above removes that part without any further work. What remains has a short list of causes: images and embeds with no reserved dimensions, so the space they need only exists once they arrive; banners and consent notices injected above content that has already been painted; and a fallback font swapping for a web font with different metrics, which reflows the text set in it.

Fifth, responsiveness to input — what happens when somebody taps. It is last for two reasons. Much of it is main-thread work from scripts, some of which the steps above will already have moved or removed. And it is the metric the lab handles worst: nobody interacts with a page during a simulated run, so the lab reports how long the main thread was blocked during the load as a proxy for it. Interaction to next paint is a field metric. If responsiveness is your real problem, field data is where you will see it.

Four kinds of slow, sorted by who can fix them

One way to split slow sites that survives contact with real ones is by who can fix them and what the fix costs. Four categories, and only the last of them means replacing the site.

The host, when the first byte is slow even for a page that should be trivial to produce, and stays slow when that page is being served from cache. Before concluding the machine is at fault, run the same test from a location near the server and from one a long way from it. Slow from both points at the server or its configuration. Slow only from a distance means you are paying for round trips, and the answer is a CDN in front of it rather than a different host. Where it does turn out to be the host, changing host can be the entire fix, and you do not need an agency to arrange that.

The theme and plugin layer, when the server answers quickly for a cached page and slowly when it has to build one, or when the page pulls in a long list of separate stylesheets and scripts that each trace back to a feature somebody switched on. The confirming test is arithmetic rather than opinion: deactivate one suspect on a copy of the site and measure again. This is fixable in place, and a page builder belongs here rather than in the rebuild category — the weight it ships is a consequence of what it was asked to render, and it can be removed without replacing the site.

The third-party scripts, which sit outside the first two because you did not write them and cannot change what they do. Their cost changes without you changing anything, and it is paid on the visitor's device rather than on your server, so a better host and a better cache do nothing about it. What makes this category different is that the decision is commercial rather than technical. Each one is doing a job for somebody in the business, and the choice is to remove it, to load it later and accept that whatever it does now happens later, or to keep it and stop treating its cost as a fault to be tuned away.

The way the page itself is produced, which is the expensive answer. The page cannot be fast because of how it arrives: content assembled in the browser, so nothing appears until a script has run and fetched it, or one markup payload sent to every device with the parts a phone does not need hidden by CSS rather than not sent. Caching helps less here than people expect, and it is worth being exact about why. Browser and CDN caching do save a returning visitor from downloading the same scripts again. What they cannot save is running them. A returning visitor may skip some of the compilation, because engines keep that, but the execution is paid in full on every load whatever the file came from. Tuning buys a slightly better number here, and being told so plainly is worth more than a task list.

You can establish which of the four you are looking at yourself, and it is worth doing before you ask anybody for a price, because it turns a vague request into a specific one.

What you can check yourself, in this order

None of this needs a specialist. What it needs is a decision rule attached to each check, because a procedure without one lets you run every test and conclude nothing.

  • Run the same URL three times, several minutes apart, and look at the spread before the number. If the runs differ from one another by about as much as the change you hope to detect, no single run can tell you whether that change worked.
  • Read time to first byte before anything else. If it accounts for more of the total than everything the browser does afterwards, stop reading the rest of the list — nothing below it can be judged, or fixed, while the first byte is late.
  • Test more than the homepage: the template carrying the most traffic, one service or product page, and one page that cannot be served from cache, such as a basket or account page. That last one is the honest measure of how quickly your server builds a page, because it is the request the cache cannot answer.
  • Compare the single-URL field figure against the site-wide one wherever both are shown. If the site-wide figure sits in a worse band, or its distribution carries a longer poor tail, the problem is on pages you have not looked at.
  • Find what the report names as the largest contentful element. If it is not what you expected, the plan you had in mind is aimed at the wrong thing.
  • Open the site on your own phone, on mobile data, in a private window so nothing is cached. Note anything that moves after you have started reading, and whether the first thing you tap responds at once — those are the two failures a report gives you as numbers and your hands give you as facts.
  • Check your own analytics before deciding the test resembles your audience: the device breakdown, and new visitors against returning. An audience of returning local customers and an audience arriving cold from ads are two different sites wearing the same score.

When this is worth paying somebody for

If the answer turns out to be the host, changing host may be the whole job and you can organise it without us. If it is one plugin doing something expensive on every request, removing it is the fix and you already know how.

Outside help earns its keep when the failing metric does not trace to a single cause and the work becomes a sequence of measurements rather than one change; when the obvious fix conflicts with something commercial, such as the third-party tool that costs the page and also produces the enquiries; and when the honest answer is a rebuild, which deserves to be argued with evidence rather than asserted.

It is worth knowing which conversation you are starting, because the engineering of it, the search consequences of it and the server underneath it are three different pieces of work.

Where this connects

Have a project?

Website, search, advertising, design or something more complicated — tell us what needs to work better.

Need a device repaired instead? Visit iRepair Labs →