completefrontend
Open lab My progress
THE WEB PERFORMANCE FIELD GUIDE

Choosing test conditions

Pick devices, CPUs, and networks that match your real users, and know what each kind of throttling fakes. The store loaded under DevTools' Slow 4G and through a relay with the same round trip and speeds, and DevTools' CPU calibration run on a fast laptop.

By the end, you can
  • 01
    Pick conditions from field dataRead your visitors' form factors and round trip times, and choose a screen, a network and a CPU to test with.
  • 02
    Say what each tool fakesTell what device mode can't copy, and where request-level and link-level throttling put their delays.
  • 03
    Keep the stopwatch the sameCalibrate the CPU for your own machine, write your conditions down, and compare only runs made the same way.

What a lab test fakes

You've changed something in the Leaf and Kettle store to make it faster. You load it on your laptop, and the photo of mint tea appears in about a tenth of a second. Is the store fast now?

For you, yes. But think of Asha, from the course's first lesson. She shops on a cheap phone, on the bus. Her phone has a small screen, a slow network and a slow processor. Your laptop has none of those. So a number from your laptop answers the question for you, not for her.

A lab test is a test you run yourself, on a machine you control, under conditions you choose. To tell you anything about Asha, it has to make your laptop pretend to be her phone. This lesson is about two choices: what to pretend, and how each tool does the pretending.

Real-life analogyTrying new shoes on the hills, not the shop's carpet

You buy walking shoes for a hike in the hills. In the shop, you walk up and down on the soft carpet, and they feel perfect. But the hike is steep and stony. To know how the shoes will feel there, you have to walk in them on hills like those. The carpet can't tell you.

In real life: The shop's soft carpet
In the lab: Your fast laptop, on its fast network
In real life: The steep, stony hills
In the lab: Your visitors' phones and networks
In real life: Shoes that feel perfect on the carpet
In the lab: A page that loads in a tenth of a second on your laptop
In real life: A walk on hills like the real ones
In the lab: A lab test that copies their screen, network and CPU

The course tried this on the store from Your toolkit and the course project. It loaded the store on a phone-sized screen in three ways, five times each:

  • As it is: straight from a server on the same laptop, with nothing slowed down.
  • With DevTools' Slow 4G: the network preset you used in The Performance panel.
  • Through a relay: a small program the course wrote. It sits between Chrome and the store. It makes the line between them as slow as the network Slow 4G stands for.

Here is when the store's photo appeared each way:

The same photo, three waysPop out in the code editor (opens in a new tab)JavaScript
// When the store's photo appeared (its LCP), in ms.// Each number is the middle one of five loads.const lcp = { asItIs: 116, devtools: 5336, relay: 4376 }; console.log(`On this laptop, as it is: ${lcp.asItIs} ms.`);console.log(`With DevTools' Slow 4G: ${lcp.devtools} ms.`);console.log(`Through the relay: ${lcp.relay} ms.`);
  • Line 1 is a comment. Largest Contentful Paint, or LCP, is the moment the biggest image or block of text appeared. On the store, that's the photo. Times are in milliseconds (ms), thousandths of a second.
  • Line 2 is a comment too. Each number is the median of five loads: put them in order and take the middle one. One odd load can't pull a median far.
  • Line 3 holds the three medians.
  • Lines 5 to 7 print On this laptop, as it is: 116 ms., With DevTools' Slow 4G: 5336 ms. and Through the relay: 4376 ms.

The picture below shows the store's screen each way, at the three moments a photo appeared.

The store's phone-sized screen, loaded three ways, at 116 ms, 4,376 ms, 5,336 ms: the moments a photo appeared. As it is: at 116 ms, the photo; at 4,376 ms, the photo; at 5,336 ms, the photo. DevTools' Slow 4G: at 116 ms, a blank screen; at 4,376 ms, words, and no photo yet; at 5,336 ms, the photo. The relay: at 116 ms, a blank screen; at 4,376 ms, the photo; at 5,336 ms, the photo.116 ms4,376 ms5,336 msas it isThe store with its photo of mint teaThe store with its photo of mint teaThe store with its photo of mint teaDevTools'Slow 4GblankThe store's words, and no photo yetThe store with its photo of mint teathe relayblankThe store with its photo of mint teaThe store with its photo of mint tea
The store's screen, loaded three ways, at the moment each photo appeared. They're real frames Chrome captured, cropped to the part under the shop's name. Outlined: the screen whose photo had just appeared. The yellow bar is the store's promotion, which comes a second after the page is ready.

At 116 ms, the store as it is already shows the photo. The other two screens are still blank. At 4,376 ms, the relay shows the photo too, but DevTools' Slow 4G still shows only words.

The first line is the shop's carpet. The other two are both meant to be the same hills: a "Slow 4G" network. Yet they're almost a second apart. Which one is Asha's? Neither, exactly. Each tool copies the network in its own way, and the way it copies changes the number.

Pick a network below. Each row is one file of the store. It shows how long the file waited for its first byte. Then it shows how long the rest took to arrive.

Playground: one store, three networks
Files, from the start0 to 5,336 ms
/0.9 ms to 572.2 ms
/styles.css578 ms to 1,156.1 ms
/app.js578.2 ms to 2,866.7 ms
/hero.svg579 ms to 5,249 ms
Paints2,928 ms, 5,336 ms

waiting for the first byte receiving the rest FCP, then LCP. Each time is when the response started, then ended.

Try it yourself
DevTools' Slow 4G

DevTools holds every request for 562.5 ms. The HTML's first byte came back 0.1 ms after the request, and the rest took 571.3 ms to arrive. The middle of 5 loads: FCP 2,892 ms, LCP 5,336 ms.

Recorded in Chrome 156 on an Apple M1 Pro: the store's own Resource Timing, from the load with the middle LCP of five. The three ways took turns, each load in a new browser context.
The main idea

A lab test makes your laptop pretend to be your visitors' devices. Choose what to pretend from your field data. Learn how each tool pretends. Then keep it the same from test to test. The same "Slow 4G" label gave the store two LCPs almost a second apart. Two tools slowed the network in two different ways.

A lab test pretends three things about a visitor's phone. Field data tells you what each one should be. On your laptop, a different tool fakes each one:

What a lab test fakes about a visitor's phone: a small screen, faked by device mode; a slow network, faked by network throttling; a slower CPU, faked by CPU throttling.What your visitors haveWhat fakes it on your laptopa small screendevice modea slow networknetwork throttlinga slower CPUCPU throttling
Your field data tells you the left side. On your laptop, a different tool fakes each row, and each tool fakes it in its own way.

The next section reads field data. After it, one section takes each row of the picture: the screen, the network and the CPU.

Using field data to pick profiles

Before you pretend anything, decide who you're pretending to be. Your laptop can't tell you that. Your visitors can.

Real-life analogyA recipe tested for your friends' ovens

You're sending a cake recipe to friends, to bake in their own kitchens. In your big, hot oven, it's done in 30 minutes. Before you write "30 minutes", you ask what ovens they have. Most have small, cooler ones. So you set your oven to match theirs, and bake it again.

In real life: Asking your friends what ovens they have
In the lab: Reading your field data
In real life: "Most have small, cooler ovens"
In the lab: "Most page loads are on phones, with slow round trips"
In real life: Setting your oven to match theirs
In the lab: Choosing a screen, a network and a CPU to test with
In real life: Oven settings you write down and reuse
In the lab: A test profile

Field data is measured during real visits, on real visitors' devices. You met it in Lab data vs field data. The biggest public source is the Chrome UX Report, or CrUX: Google's dataset of how real Chrome users experience websites. It answers two of your questions.

A test profile is what you build from the answers: one screen, one network and one CPU to test with. Like the oven settings, you write it down and reuse it.

Phone, tablet or desktop?

CrUX sorts page loads into three form factors: phone, tablet and desktop. Its docs say how it tells them apart: "Form factor is inferred from the device User-Agent string." The User-Agent is a line of text the browser sends with each request. It says which browser it is, and what it's running on.

How slow are their networks?

For the network, CrUX gives a round trip time. A round trip is a message going from the device to a server, and the answer coming back. The docs call it "an estimate of the HTTP (application layer) round trip time at the start of the navigation, based on recent network connections." In plainer words: as a page starts loading, the browser estimates the round trip from the connections it made recently.

Notice whose number it is. In the docs' words, it's "a measure of the users to your site (based on their recent internet activity), and not of the site itself." It describes your visitors' networks, not your server.

CrUX used to sort networks into labels instead, such as "4g" and "3g", called effective connection types. The docs record the change: "The Effective Connection Type dimension was removed from February 2025 and replaced with the RTT metric." RTT is short for round trip time.

Two real sites, two profiles

Here is what CrUX's public data says about two real sites, for one month:

Who visits two real sitesPop out in the code editor (opens in a new tab)JavaScript
// Who visits two real sites, from one month of CrUX data.const sites = [  { site: "en.wikipedia.org", phones: 0.7959, roundTrip: 100 },  { site: "developer.mozilla.org", phones: 0.2236, roundTrip: 125 },]; for (const { site, phones, roundTrip } of sites) {  const percent = Math.round(phones * 100);  console.log(`${site}: ${percent}% on phones; 3 in 4 round trips took ${roundTrip} ms or less.`);}
  • Line 1 is a comment.
  • Lines 3 and 4 are recorded from CrUX. phones is the share of page loads on phones: 0.7959 means 79.59%.
  • roundTrip is the round trip at the 75th percentile. Sort every page load's round trip from shortest to longest, and take the one three-quarters of the way along. Three in four page loads had that round trip or less.
  • Line 8 turns the share into a whole percentage.
  • Line 9 prints en.wikipedia.org: 80% on phones; 3 in 4 round trips took 100 ms or less. and developer.mozilla.org: 22% on phones; 3 in 4 round trips took 125 ms or less.

So the two sites need different first tests. Most of Wikipedia's page loads are on phones, so its first profile is a phone. Most of MDN's are on desktops, so it starts with a desktop, and tests a phone second.

Now the network. Lighthouse's default network, Slow 4G, has a 150 ms round trip. Its docs say Slow 4G stands for "roughly the bottom 25% of 4G connections and top 25% of 3G connections." Both sites' round trips are shorter than that. So Slow 4G is slower than the round trips of 3 in 4 of their page loads. That makes it a fair test of a slow day. If your own visitors' round trip is longer than 150 ms, test with a slower network.

You don't have to compare by hand. The Performance panel reads your field round trip and suggests the closest network preset.

What CrUX can't tell you

CrUX doesn't sort page loads by CPU. It splits them only by form factor and, in its BigQuery tables, by country. So it can say "mostly phones", but not which phones. For the CPU, you choose a kind of phone yourself, as the CPU section shows.

Your own field data can collect more. Any page can read two hints about the device it runs on:

  • navigator.connection.rtt is the browser's estimate of the round trip, in ms. CrUX's round trip is based on this same property. Firefox and Safari don't have it.
  • navigator.hardwareConcurrency is the number of logical processors: roughly, how many things the CPU can work on at once. Throttling and simulation met it too.

Why it matters: a test profile is only a guess until field data backs it. Test the form factor most of your page loads use. Test it on a network at least as slow as their round trips.

Real devices vs emulation

You've chosen a phone. You open DevTools and turn on the device toolbar. You pick a phone-sized screen, and the store looks the way it does on Asha's phone. Is your laptop a phone now?

Real-life analogyTrying on glasses in a phone app

An optician's app shows new frames on your face, through your phone's camera. You can see their shape, their colour and their size. You can't feel their weight on your nose, or whether they pinch after an hour. For that, you go to the shop and wear them.

In real life: The frames on your face, in the app
In the lab: Device mode: the phone's screen size and touch
In real life: The weight and the pinch you can't feel
In the lab: The phone's own CPU: your code still runs on the laptop
In real life: Wearing the real glasses in the shop
In the lab: Running the page on a real phone, with remote debugging

No. The toolbar turns on device mode: a set of DevTools features that imitate a phone. Imitating one device on another is called emulation. Device mode can copy:

  • The phone's screen size, and how many screen pixels it uses for each CSS pixel.
  • Touch, so a tap fires touch events instead of clicks.
  • A slower CPU and a slower network.
  • From the Sensors panel, where the phone is and which way up it's held.

Its docs are honest about what that adds up to. "Think of device mode as a first-order approximation of how your page looks and feels on a mobile device. With device mode you don't actually run your code on a mobile device." A first-order approximation is a first, rough answer: close enough to start with, but not the final one.

The docs name one gap in particular: the processor. "There are some aspects of mobile devices that DevTools will never be able to simulate. For example, the architecture of mobile CPUs is very different than the architecture of laptop or desktop CPUs." CPU throttling makes your laptop's CPU get less done each second. It's still a laptop CPU, built differently from a phone's.

So use each one for what it's good at:

  • Device mode is quick. Use it while you work: change something, reload, look again.
  • A real phone is the check. The docs' advice: "When in doubt, your best bet is to actually run your page on a mobile device."

You keep DevTools on a phone, too. Remote debugging connects DevTools on your laptop to Chrome on an Android phone, through a USB cable. The docs say you can then "view, change, debug, and profile a page's code from your laptop or desktop while it actually runs on a mobile device." Setting it up takes three steps:

  1. On the phone, turn on USB debugging in its developer options.
  2. Plug the phone into your laptop, and accept the prompt on the phone's screen.
  3. On the laptop, open chrome://inspect#devices in Chrome. Each tab open on the phone is listed there. Click Inspect next to one to open DevTools for it.

Lighthouse can test a real phone too. Throttling and simulation showed the settings: provided throttling and a CPU slowdown of 1. The phone is already slow, so Lighthouse mustn't slow it down again.

Why it matters: a number from device mode is a number from your laptop in a phone costume. Before you tell your team "it's fast on phones", check on a phone.

Packet-level vs browser-level network throttling

Back to the puzzle from the start. DevTools' Slow 4G and the relay copy the same network: a 150 ms round trip, and 1.6 Mbps down. Mbps, megabits per second, is how much data a line carries each second. Yet the store's photo came almost a second apart. To see why, look at where each copy adds its delay.

Real-life analogyTwo copies of the same hill road

A delivery firm in town wants to know how long its parcels would take to reach the hills. One manager holds every parcel at the depot for the same fixed time, then lets it out slowly. Another builds a copy of the hill road: long, with one narrow lane that every van shares. On that road, each new van must phone ahead and wait for a reply before it sets off.

In real life: The same fixed hold on every parcel
In the lab: DevTools' Slow 4G: 562.5 ms added to every request
In real life: Letting the parcel out slowly
In the lab: The wait showing up as receiving time
In real life: Phoning ahead before a new van's first trip
In the lab: A new connection's handshake: one round trip
In real life: One narrow lane, one van after another
In the lab: The relay: one line, shared by every connection

On a real network, data doesn't travel in one lump. It's cut into small pieces called packets, and the network delays each packet. Slowing a network down on purpose is called throttling it. Lighthouse's docs sort the ways to do it by where they add the delay.

Read each row across: the kind of throttling, what it slows down, and what Lighthouse's docs say about it.

Three kinds of network throttling
KindWhat it slows downWhat Lighthouse's docs say
Request-level, like DevToolsEach request. It holds the response back for a fixed time, then lets it through slowly.It "isn't highly accurate". Real delays happen "at the packet level rather than the request level".
Proxy-levelEverything that passes through a proxy: a program that sits between the browser and the server.It's "decent, but not ideal". It doesn't slow UDP data.
Packet-levelEvery packet the computer sends and receives, for every program on it.It can make "the most accurate network simulation", but it "can introduce more variance". It needs sudo.

Two words from the table. UDP is a very simple way to send packets, the one HTTP/3 travels on, as HTTP/3 and QUIC showed. sudo runs a command with administrator rights.

How DevTools copies Slow 4G

DevTools throttles at the request level. Its Slow 4G holds every request for 562.5 ms. It also caps the download speed at 1.44 Mbps, a tenth under 1.6.

The hold is much longer than the 150 ms round trip, on purpose. As The Performance panel explained, the extra makes up for not delaying each packet.

How the relay copies it

The relay slows the line instead. It sits between Chrome and the store, like a proxy. It behaves like one slow line:

  • Every message takes half a round trip, 75 ms, to cross it.
  • Bytes cross at 1.6 Mbps down and 750 kbps up, one after another, in the order they reached it. Every connection shares the same line.
  • A new connection waits one round trip before its first request can cross. That's its handshake: the "hello" and "hello back" that open a TCP connection, from TCP connections and slow start.

Chrome opened 3 connections in every load, so every relay load paid for 3 handshakes. The relay isn't a packet-level tool either. For one thing, it doesn't copy TCP's slow start: each file crosses at full speed from its first byte. It's a second copy of the same network, made a different way.

Same label, two results

Here are all fifteen loads, five each way. Beside the photo, they include the first paint. First Contentful Paint, or FCP, is the moment the first text or image appeared.

Fifteen loads, three waysPop out in the code editor (opens in a new tab)JavaScript
// Five loads of the store each way, taking turns: FCP and LCP in ms.const loads = {  none: { fcp: [196, 108, 116, 100, 152], lcp: [196, 108, 116, 100, 152] },  devtools: { fcp: [2908, 2876, 2892, 2884, 2928], lcp: [5344, 5324, 5348, 5336, 5336] },  link: { fcp: [1452, 1416, 1448, 1400, 1400], lcp: [4372, 4376, 4376, 4376, 4376] },};const median = (list) => [...list].sort((a, b) => a - b)[Math.floor(list.length / 2)]; for (const [condition, { fcp, lcp }] of Object.entries(loads)) {  console.log(`${condition}: FCP ${median(fcp)} ms, LCP ${median(lcp)} ms`);}
  • Line 1 is a comment. The three ways took turns: one load each, then round again, five times.
  • Lines 3 to 5 are recorded: each load's FCP and LCP, in ms. none is the store as it is, and link is the relay.
  • Line 7 finds a median. It sorts a copy of the list, and takes the middle value.
  • Lines 9 to 11 print one line for each way. They print none: FCP 116 ms, LCP 116 ms, devtools: FCP 2892 ms, LCP 5336 ms and link: FCP 1416 ms, LCP 4376 ms.

DevTools' copy came out slower: the photo almost a second later, and the first paint about twice as late. It wasn't luck, either. Every DevTools load was slower than every relay load.

Most of the photo's extra second comes from two differences:

  • The hold. DevTools held each request for 562.5 ms. The relay's wait was a round trip or two: 150 ms on a connection already open, 300 ms on a new one.
  • The speed. DevTools' line was a tenth slower, and the photo alone is 580 KB.

Why it matters: a preset's name doesn't tell you how it was made. Two tools can both say "Slow 4G", and disagree by a second on the same page.

Where the wait shows up

The two copies also put their wait in different places. Here is the store's HTML file in one load each way. The times come from the page's own Resource Timing: the times the browser writes down for every file it fetches.

Where the HTML's time wentPop out in the code editor (opens in a new tab)JavaScript
// The HTML's Resource Timing in one load each way, in ms from the start of the visit.const html = {  devtools: { requestStart: 0.8, responseStart: 0.9, responseEnd: 572.2 },  link: { requestStart: 0.9, responseStart: 306, responseEnd: 306.2 },}; for (const [condition, timing] of Object.entries(html)) {  const waiting = timing.responseStart - timing.requestStart;  const receiving = timing.responseEnd - timing.responseStart;  console.log(`${condition}: the HTML waited ${waiting.toFixed(1)} ms, then took ${receiving.toFixed(1)} ms to arrive.`);}
  • Line 1 is a comment. Times are in ms from the start of the visit.
  • Lines 3 and 4 are recorded. requestStart is when the request left. responseStart is when the first byte of the answer came back, and responseEnd is when the last byte did.
  • Line 8 works out the waiting: from the request to the first byte. Line 9 works out the receiving: from the first byte to the last.
  • Line 10 prints devtools: the HTML waited 0.1 ms, then took 571.3 ms to arrive. and link: the HTML waited 305.1 ms, then took 0.2 ms to arrive.
The HTML's Resource Timing: DevTools' Slow 4G, waiting 0.1 ms and receiving 571.3 ms; the relay, waiting 305.1 ms and receiving 0.2 ms.DevTools' Slow 4G571.4 msthe relay305.3 ms
The same small HTML file, through two copies of Slow 4G. Shaded: waiting for the first byte. Plain: receiving the rest. DevTools' wait is almost all plain; the relay's is almost all shaded.

Through the relay, the HTML waited two round trips. One was for the handshake, and one for the request and its answer. Then the small file arrived at once. Under DevTools, the first byte came back at once. The 562.5 ms hold showed up while the rest of the file arrived. DevTools held back the body of the response, not its first bytes.

Why it matters: time to first byte, or TTFB, is measured up to that first byte. Under DevTools' throttling, the HTML's first byte came back almost at once. So a TTFB from a DevTools-throttled load leaves out the network's wait. Read the waiting and the receiving together. Compare them only with tests that used the same kind of throttling.

Same set-up, every time

Now picture testing the store every week. Last week you used the relay: LCP 4,376 ms. This week a teammate used DevTools' Slow 4G: LCP 5,336 ms. Nobody touched the store, and it looks 960 ms slower.

Real-life analogyTiming the walk from the same start to the same finish

Ravi times his walk to the tea shop every morning, to see if a new shortcut helps. He uses the same stopwatch, starts at his front door, and stops at the shop's door. One morning he starts at the corner instead, and the walk is two minutes shorter. The shortcut didn't do that. The start moved.

In real life: The same stopwatch, start and finish
In the lab: The same screen, network preset, kind of throttling and CPU rate
In real life: Today's time beside yesterday's
In the lab: This week's LCP beside last week's
In real life: Starting at the corner instead of the door
In the lab: Switching from the relay to DevTools' Slow 4G
In real life: Two minutes that weren't the shortcut
In the lab: 960 ms that weren't the page

A lab test is that stopwatch. Write down how it was set up. Keep it the same for every run you compare:

  • The screen: which device, at what size.
  • The network preset, and the tool that applied it.
  • The CPU rate, and the machine it was worked out on. The next section shows why.
  • The tool itself, such as DevTools or Lighthouse, and its version.

Even with everything the same, two runs still differ a little. Noise and variability, the next lesson, shows how to compare them honestly.

CPU throttling on a fast laptop

The last row of the picture is the CPU. You've met its problem twice already. In The Performance panel, you walked at Ravi's pace. There, "five times slower" means something different for every walker. So DevTools times the walk instead. In Throttling and simulation, one pace rule for a whole team left the slow runners barely moving.

Lighthouse's docs put it in one line: "CPU throttling is expressed relative to the performance of the host device." The host is the computer running the test. So 6x on a fast laptop and 6x on an old one copy two different phones.

DevTools' CPU menu offers two kinds of preset:

  • Fixed presets use the same rate on every machine. That's 4x for "mid-tier mobile" and 6x for "low-tier mobile".
  • Calibrated presets are worked out for your machine. DevTools runs a benchmark, a small test program that counts how much work the CPU gets done. Then it searches for the slowdown at which your machine scores like a real phone.

The scores it aims for come from DevTools' source. A mid-tier phone, "like a Pixel 5", scores 1000. A low-tier one, "like a Moto G4 Power 2022", scores 264. The course ran the same benchmark on its laptop, an Apple M1 Pro. At full speed, it scored 3,192. Then the course ran it at each preset, three times each.

The fixed presets miss

The fixed presets on this laptopPop out in the code editor (opens in a new tab)JavaScript
// DevTools' fixed CPU presets on this laptop: the benchmark's score, and a real phone's.const presets = [  { name: "Mid-tier mobile, 4x", score: 774.5, phone: 1000 },  { name: "Low-tier mobile, 6x", score: 510, phone: 264 },]; for (const { name, score, phone } of presets) {  const percent = Math.round((score / phone) * 100);  console.log(`${name} scored ${score}: ${percent}% of the phone's score.`);}
  • Line 1 is a comment.
  • Lines 3 and 4 are recorded. Each holds a preset's median score on this laptop, beside the score of the phone it's meant to copy.
  • Line 8 turns the laptop's score into a percentage of the phone's. Over 100% means faster than the phone.
  • Line 9 prints Mid-tier mobile, 4x scored 774.5: 77% of the phone's score. and Low-tier mobile, 6x scored 510: 193% of the phone's score.

On this laptop, 4x makes a CPU a little slower than a mid-tier phone. 6x makes one almost twice as fast as a low-tier phone. Say you test at 6x here and find "it's fine on cheap phones". You've really tested a phone twice as fast as a cheap one.

The calibrated presets land on the phones

The calibrated presets on this laptopPop out in the code editor (opens in a new tab)JavaScript
// DevTools' calibrated CPU presets on this laptop: the benchmark's score, and a real phone's.const presets = [  { name: "Calibrated mid-tier, 3.09x", score: 1008.5, phone: 1000 },  { name: "Calibrated low-tier, 11.7x", score: 261.5, phone: 264 },]; for (const { name, score, phone } of presets) {  const percent = Math.round((score / phone) * 100);  console.log(`${name} scored ${score}: ${percent}% of the phone's score.`);}
  • Lines 3 and 4 are recorded. They hold the rates DevTools' calibration found on this laptop, 3.09x and 11.7x. Beside each is the benchmark's score at that rate.
  • Lines 7 to 10 are the same loop as before. Line 9 prints Calibrated mid-tier, 3.09x scored 1008.5: 101% of the phone's score. and Calibrated low-tier, 11.7x scored 261.5: 99% of the phone's score.
The benchmark at DevTools' CPU rates on this laptop: Mid-tier mobile, 4x, 774.5; Low-tier mobile, 6x, 510; Calibrated mid-tier, 3.09x, 1008.5; Calibrated low-tier, 11.7x, 261.5. DevTools aims for 1000 for a mid-tier phone and 264 for a low-tier one.10002644x6x3.09x11.7x1x4x8x12x
The two lines are the phones' scores. On this laptop, the fixed 4x lands below the mid-tier line, and the fixed 6x lands far above the low-tier one. The shaded dots, the calibrated rates, sit on their lines.

The calibrated rates land on both phones. Look how far they are from the fixed ones. To copy a low-tier phone, this laptop needed 11.7x, nearly twice the fixed 6x. DevTools found that rate with the search you watched in The Performance panel. It tries a rate and runs the benchmark. Then it tries halfway between the rates still left.

The search runs again each time you calibrate, and the benchmark varies a little from run to run. Three calibrations on this laptop gave mid-tier rates of 3.12x, 3.09x and 3.09x, and low-tier rates of 10.78x, 11.7x and 11.72x. So calibrate once, and write the rates down with the rest of your set-up. Lighthouse's docs make the same point: "it's important to calibrate your device before attempting to compare different reports."

Try the benchmark on your own device. It runs the same test DevTools calibrates with, here in this tab.

Playground: your device
This devicelive
Benchmark
not run yet
Phones' scores
mid-tier 1000, low-tier 264
Logical processors
not available in this browser
Memory
not available in this browser
Round trip
not available in this browser
Connection type
not available in this browser
Try it yourself
Lighthouse's benchmark, in your browser

Runs the benchmark DevTools calibrates with, 250 ms at a time: once to warm up, then three more times. The page freezes for about a second while it runs.

Live: the benchmark runs in this tab, and the hints below are what your browser tells any page. Nothing is sent anywhere.

Why it matters: a CPU rate is only half a setting. The other half is the machine it ran on. Write both down, like the stopwatch's start and finish.

Request-level or link-level?

Each item below describes one of the two copies of Slow 4G, from this lesson's loads. Was it DevTools' request-level throttling, or the relay's one slow line?

Request-level or link-level?
  • Holds every request for the same fixed time
  • Resource Timing shows the delay as receiving
  • You turn it on from the Network panel's throttling menu
  • A new connection costs a round trip first
  • Resource Timing shows the delay as waiting
  • The photo's first bytes came only after app.js had arrived
Try it yourself
0 of 6 correct

Sort each item by the copy of Slow 4G it describes. Every item comes from the course's loads.

Choose a category for every card. You can change an answer at any time; Reset clears them all.

Common mix-ups

  • "My laptop's numbers are close enough." No. The store's photo appeared at 116 ms on this laptop as it is. On either copy of Slow 4G, it took more than 4 seconds.
  • "Slow 4G is Slow 4G." No. DevTools' copy and the relay's gave the same store LCPs of 5,336 and 4,376 ms.
  • "DevTools' time to first byte includes the network's wait." No. Under DevTools, the HTML's first byte came back at once. The wait showed up while the rest of it arrived.
  • "6x always means a low-tier phone." No. On this laptop, 6x scored 510 on the benchmark. A low-tier phone scores 264.
  • "Device mode runs my page like a phone." No. It copies the screen, touch, and a slower network and CPU. Your code still runs on the laptop's CPU.
  • "CrUX tells me my visitors' connection type." No. Since February 2025, it gives a round trip time instead of a label like "4g".

Practice exercises

Answer first, then use the hints.

Exercise 1 · Warm-upOne slow load

Suppose one relay load had been slow, with an LCP of 4,900 ms. The code below has that change. What would its last line print?

Starter codePop out in the code editor (opens in a new tab)JavaScript
// Five loads of the store each way, taking turns: FCP and LCP in ms.
const loads = {
  none: { fcp: [196, 108, 116, 100, 152], lcp: [196, 108, 116, 100, 152] },
  devtools: { fcp: [2908, 2876, 2892, 2884, 2928], lcp: [5344, 5324, 5348, 5336, 5336] },
  link: { fcp: [1452, 1416, 1448, 1400, 1400], lcp: [4372, 4376, 4376, 4900, 4376] },
};
const median = (list) => [...list].sort((a, b) => a - b)[Math.floor(list.length / 2)];

for (const [condition, { fcp, lcp }] of Object.entries(loads)) {
  console.log(`${condition}: FCP ${median(fcp)} ms, LCP ${median(lcp)} ms`);
}

Answer, then press Check. Spacing and letter case don’t matter.

    Exercise 2 · Warm-upA slower laptop

    On a slower laptop, the 6x preset scored 396 instead of 510. What would the second line print?

    Starter codePop out in the code editor (opens in a new tab)JavaScript
    // DevTools' fixed CPU presets on this laptop: the benchmark's score, and a real phone's.
    const presets = [
      { name: "Mid-tier mobile, 4x", score: 774.5, phone: 1000 },
      { name: "Low-tier mobile, 6x", score: 396, phone: 264 },
    ];
    
    for (const { name, score, phone } of presets) {
      const percent = Math.round((score / phone) * 100);
      console.log(`${name} scored ${score}: ${percent}% of the phone's score.`);
    }

    Answer, then press Check. Spacing and letter case don’t matter.

      Exercise 3 · PracticeThe photo's wait

      In the first playground, pick The relay. When did hero.svg's response start?

      Answer, then press Check. Spacing and letter case don’t matter.

        Exercise 4 · PracticeThe file before the first paint

        In the first playground, pick DevTools' Slow 4G. Which file finished arriving just before the first paint, FCP?

        Answer, then press Check. Spacing and letter case don’t matter.

          Exercise 5 · ChallengeA tool that slows packets

          Lighthouse's throttling docs name a well-known testing tool that uses packet-level throttling. Which tool is it?

          Answer, then press Check. Spacing and letter case don’t matter.

            Exercise 6 · ChallengeTouch or click

            Open DevTools on this page and turn on the device toolbar. Its Device Type list sets how the page is drawn, and which events a tap fires. Which option draws the page like a phone, but fires click events instead of touch events?

            Answer, then press Check. Spacing and letter case don’t matter.

              Check your understanding

              For each question, ask three things: who visits, what the tool fakes, and on which machine it ran.

              Test conditions quiz · 7 questionsScore: first tries count
              1. Question 1 of 7What does the second line of the fifteen loads example print?

                Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
                // Five loads of the store each way, taking turns: FCP and LCP in ms.
                const loads = {
                  none: { fcp: [196, 108, 116, 100, 152], lcp: [196, 108, 116, 100, 152] },
                  devtools: { fcp: [2908, 2876, 2892, 2884, 2928], lcp: [5344, 5324, 5348, 5336, 5336] },
                  link: { fcp: [1452, 1416, 1448, 1400, 1400], lcp: [4372, 4376, 4376, 4376, 4376] },
                };
                const median = (list) => [...list].sort((a, b) => a - b)[Math.floor(list.length / 2)];
                
                for (const [condition, { fcp, lcp }] of Object.entries(loads)) {
                  console.log(`${condition}: FCP ${median(fcp)} ms, LCP ${median(lcp)} ms`);
                }

                Choose an answer to see the explanation.

              2. Question 2 of 7What does the second line of the fixed presets example print?

                Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
                // DevTools' fixed CPU presets on this laptop: the benchmark's score, and a real phone's.
                const presets = [
                  { name: "Mid-tier mobile, 4x", score: 774.5, phone: 1000 },
                  { name: "Low-tier mobile, 6x", score: 510, phone: 264 },
                ];
                
                for (const { name, score, phone } of presets) {
                  const percent = Math.round((score / phone) * 100);
                  console.log(`${name} scored ${score}: ${percent}% of the phone's score.`);
                }

                Choose an answer to see the explanation.

              3. Question 3 of 7Both copies of Slow 4G used a 150 ms round trip and 1.6 Mbps. Why did the store's photo appear later with DevTools' copy?

                Choose an answer to see the explanation.

              4. Question 4 of 7What does DevTools' device mode say it will never be able to simulate?

                Choose an answer to see the explanation.

              5. Question 5 of 7Your CrUX data shows most page loads on phones, and a 75th percentile round trip of 300 ms. What should your lab tests use?

                Choose an answer to see the explanation.

              6. Question 6 of 7On a fast laptop, why calibrate the CPU instead of using DevTools' fixed 6x preset?

                Choose an answer to see the explanation.

              7. Question 7 of 7Last week the relay gave the store an LCP of 4,376 ms. This week DevTools' Slow 4G gave 5,336 ms, and nobody changed the page. What do you conclude?

                Choose an answer to see the explanation.

              Key takeaways

              • Your laptop as it is shows the shop's carpet. A lab test has to copy your visitors' screen, network and CPU.
              • Choose what to copy from field data. CrUX gives the form factor and, since February 2025, a round trip time. It doesn't give the CPU.
              • Device mode is a first, rough answer. Check on a real phone, with remote debugging.
              • DevTools holds each request; the relay slowed the line. The same "Slow 4G" gave different numbers, and put the wait in different places.
              • A CPU rate depends on the machine it runs on. Calibrate, and write the rate down.
              • Keep the whole set-up the same for every run you compare.

              Remember the one-liner.
              Test like your visitors, know what your tools fake, and set the stopwatch up the same way every time.

              Sources

              The facts on this page come from these docs and source files:

              Coming next: Noise and variability. Even with the same set-up, two runs give different numbers. You'll see where that noise comes from, and how to compare runs honestly.

              CompleteFrontend Clear concepts. Working examples.