A JMeter page sampler retrieving twenty embedded assets reports 4-second samples. What is it timing?
answer
- One sampler, one container, many children
- End time moves, bytes add up
- Latency stayed behind with the page
- Children are renamed by position
basics
~20 sThe container sample. It starts when the page request started and ends when the last asset finished, so it covers all twenty-one requests. Bytes are summed as well; only Latency still belongs to the page alone.
solid answer
~40 sOnce the parser finds embedded URLs, JMeter clones the page result into a **container**, files the page inside it as the first child and adds every asset as a further child. Each child extends the container's end time to its own and adds its bytes, so the elapsed time you see spans the whole fan-out and the byte count is the sum. Success is `AND`-ed, so one failed asset turns the container red with a message naming the URL, unless `httpsampler.ignore_failed_embedded_resources=true`. Latency is copied from the page and never updated, which is why comparing container elapsed time with container Latency shows the fan-out directly. In the JTL, `jmeter.save.saveservice.subresults` defaults to `true`, so the container plus twenty-one children means twenty-two rows for that one sampler.
code
text · 6 linestimeStamp,elapsed,label,responseCode,success,bytes,Latency,URL
1757400000123,4012,Home Page,200,true,842190,86,https://shop.example.invalid/
1757400000123,91,Home Page-0,200,true,18422,86,https://shop.example.invalid/
1757400000214,142,Home Page-1,200,true,64110,58,https://shop.example.invalid/static/app.css
1757400000356,205,Home Page-2,200,true,231884,61,https://shop.example.invalid/static/app.js
1757400003930,205,Home Page-20,200,true,15230,55,https://shop.example.invalid/img/footer.pnggo deeper
Recall that a sampler with embedded resources produces a parent result with children, and that the parent's number is not one request's response time.
Explain the aggregation precisely: end time extended, bytes summed, success ANDed, latency left alone, and one JTL row per child.
Diagnose from the artefacts — compare container elapsed time against Latency and bytes, read the rewritten error message, and pick between parallel downloads, the URL regexes and explicit samplers.
Own the reporting consequence: decide whether page-level containers or per-asset samplers are what your dashboards and thresholds are built on, and make the choice uniform so numbers stay comparable across releases.
The number is real, and it is not a lie about the network. It is the **container sample**, and a container sample times something different from what its name suggests. ## What JMeter built behind the label With **Retrieve All Embedded Resources** on, the sampler no longer returns the page result. Once the parser finds at least one URL, JMeter creates a new result by cloning the page result, files the page result inside it as the first child, and then adds each asset response as a further child. That clone is what your listener shows under the sampler's name. Cloning copies the page's start time, latency, bytes and success flag. Each child added afterwards then updates the container: - **End time** moves to the later of the current end time and the child's end time, and elapsed time is recomputed as `endTime - startTime - idleTime`. - **Bytes**, sent bytes, header size and body size are **added**. - **Success** is `AND`-ed: one failed child makes the container fail, and its response message is rewritten to `Embedded resource download error: <url> code:… message:…`. - **Latency is not touched.** So for a page followed by twenty serial asset calls, the container's elapsed time spans the page's first byte out to the twentieth asset's last byte — the four seconds — while its Latency is still the page's own time to first byte, and its byte count is the page plus all twenty assets. Nothing here is inconsistent with 200 ms per request; twenty-one of them in sequence is what four seconds looks like. ## What the results file actually contains `jmeter.save.saveservice.subresults` defaults to `true`, so the results collector writes the container row and then recurses into its children, one row each. A page with twenty assets contributes **twenty-two rows**: the container, the page itself, and the twenty assets. The labels are the second surprise. Since JMeter 5.0 the SubResult Naming Policy renames every child by position: a child's label becomes `<parent label>-<n>`, numbering from zero. So the rows read `Home Page`, `Home Page-0`, `Home Page-1` … `Home Page-20`, not the asset URLs. `Home Page-7` is the eighth thing extracted from *this* response, which is not necessarily the same asset in the next iteration. The URL column still carries the real address. Setting `subresults.disable_renaming=true` (or running in functional mode) restores URL labels. ## How to read the run instead 1. **Look at the children, not the container**, when you want per-request times. The container is a page-level number by construction. 2. **Compare the container's Latency with its elapsed time.** A large gap is the fan-out, not a slow server. 3. **Check the container's byte count** against the page alone — the sum is the giveaway that assets were fetched. 4. **Look for the rewritten response message** if the container is red; it names the failing URL and its code. ## The levers you have - **Parallel downloads. Number:** turns the serial loop into a bounded concurrent fetch, so the container's elapsed time becomes roughly the page plus one wave per batch of *n* assets — twenty assets at the default six is about four waves, not twenty serial requests. Setting it to `1` is a no-op that logs a warning and reverts to serial. - **URLs must match** / **URLs must not match** cut the asset list before anything is fetched. - `httpsampler.ignore_failed_embedded_resources=true` stops a single failed asset from failing the container. - `httpsampler.separate.container=false` reverts to the pre-fix behaviour of not creating a separate container at all. - Turning the flag off and writing explicit samplers for the assets you care about gives you stable labels and per-asset timings, at the cost of maintaining the list. Whether a page-level number is the *right* number for the load you are modelling is a workload-design question and belongs to the performance-workloads material, not to the sampler. What belongs here is knowing exactly which requests that one number covers.
- Why does the container's Latency stay small while its elapsed time grows?The container is built by cloning the page result, which copies its latency. Adding a child only updates end time, elapsed time and the byte counters; nothing recomputes latency. So the container reports the page's time to first byte next to a duration covering every asset — the gap between the two is the fan-out.
- Your JTL shows rows labelled Home Page-7. Which asset is that?Whatever was the eighth URL extracted from that particular response. Since JMeter 5.0 sub-samples are renamed by position as `<parent>-<n>` from zero, so the label is not stable across iterations if the page's asset list changes. The URL column still holds the real address, and `subresults.disable_renaming=true` restores URL labels.
- One asset 404s. What does the page sampler report?Failure. JMeter ANDs each child's success into the container and rewrites the container's response message to `Embedded resource download error:` followed by the failing URL, its code and its message. Setting `httpsampler.ignore_failed_embedded_resources=true` keeps the container successful and leaves the failure visible only on the child row.
It is the difference between timing a supermarket trip and timing one item at the till. The container sample is the whole trip from the door; the children are the individual scans, and only they tell you whether any single scan was slow.
saying these in an interview costs you the question
- Blames the network for a number the container aggregated
- Reads container Latency as the page's full response time
- Thinks the container's bytes are just the HTML
- Assumes one failed asset leaves the page sampler green
- Believes each child row is labelled with its URL