A 4-minute JMeter run's dashboard shows only four points per over-time graph. What do you change?
answer
- A single property drives the time axis
- Its default is a whole minute
- There is a documented lower bound
- No new run is needed to change it
basics
~10 sLower jmeter.reportgenerator.overall_granularity. It defaults to 60000 milliseconds, so every over-time graph gets one point per minute. Set it in user.properties, keep it above 1000, and regenerate the existing results file.
solid answer
~40 s`jmeter.reportgenerator.overall_granularity` is the bucket width, in milliseconds, of the dashboard's over-time graphs, and it ships as `60000` — one point a minute, which is four points for a four-minute run. In `bin/reportgenerator.properties` each over-time graph definition refers to it, for example `jmeter.reportgenerator.graph.hitsPerSecond.property.set_granularity=${jmeter.reportgenerator.overall_granularity}`, so changing the one value moves them all together. That file carries a `THIS FILE SHOULD NOT BE MODIFIED` banner: copy the key into `bin/user.properties` and change it there. Two things to know before you do. The documented floor is 1000 ms — below that the throughput graphs are wrong, and nothing validates the value you set. And you do not need a new run: the property is read when the report is generated, so `jmeter -g results.jtl -o dashboard-fine` re-renders the same file at the new resolution.
go deeper
Know that the dashboard's over-time graphs use one-minute buckets by default and that a single report generator property controls it. Recalling the name and the default is enough at this level.
Explain that the graph definitions reference the property with ${...}, that a set_granularity key becomes a setter call on the graph, and that the value is read at report generation time.
Diagnose the flat, four-point graph as a granularity mismatch rather than a data problem, fix it by regenerating the existing file, and know the 1000 ms floor is unvalidated and silently produces wrong throughput.
Decide where report settings live so that the same results file renders identically for everyone, rather than depending on which engineer's local JMeter installation produced the folder.
## What the property controls `jmeter.reportgenerator.overall_granularity` is a duration in milliseconds. It is the width of the time bucket that every over-time graph in the dashboard aggregates into a single plotted point. Shipped default: `60000`. A run of four minutes therefore has roughly four buckets, and each graph is a handful of points joined by a line. The value is not read directly by the graphs. `bin/reportgenerator.properties` defines it once and then references it from each graph definition: ```properties jmeter.reportgenerator.overall_granularity=60000 jmeter.reportgenerator.graph.activeThreadsOverTime.property.set_granularity=${jmeter.reportgenerator.overall_granularity} jmeter.reportgenerator.graph.responseTimesOverTime.property.set_granularity=${jmeter.reportgenerator.overall_granularity} jmeter.reportgenerator.graph.hitsPerSecond.property.set_granularity=${jmeter.reportgenerator.overall_granularity} ``` A `property.set_<name>` key is turned into a setter call on the graph class — `set_granularity` becomes `setGranularity(...)` — which is why one property can drive a dozen graphs. ## Which graphs it does and does not move - **Moved by it:** the over-time family — active threads, response times, latencies, connect time, percentiles over time, bytes throughput, hits per second, codes per second, transactions per second, total TPS, and the two "vs request" graphs. - **Not moved by it:** `responseTimeDistribution`, which has its own literal `set_granularity=100` because its axis is response time rather than clock time; and graphs with no time axis at all, such as the response time percentiles graph. So lowering the overall value makes the time series finer and leaves the distribution histogram exactly as it was. ## The floor at 1000 ms The shipped comment is explicit: the granularity must be higher than 1000 (one second), otherwise the throughput graphs will be incorrect. The rate aggregator scales its accumulated value by `1000 / granularity` to express a per-second figure, and sub-second buckets break that arithmetic. Two practical consequences: 1. There is no validation. Setting `500` is accepted silently and produces plausible-looking, wrong throughput curves — the most dangerous kind of misconfiguration. 2. Values just above the floor are legal but rarely useful: at `1000` ms you get one point per second and the graphs become dense enough to be hard to read for a long run. A sensible working range is a few seconds for short runs and the default minute for anything long. ## Changing it without re-running The property is read when the report is generated, not when the samples are collected. The generator loads `bin/reportgenerator.properties` and then overlays the current JMeter properties, so a value in `bin/user.properties` wins. That means the fix for the four-point graph is not another test: 1. add `jmeter.reportgenerator.overall_granularity=5000` to `user.properties`; 2. run `jmeter -g results.jtl -o dashboard-5s` against the results file you already have; 3. compare the two folders if you want both resolutions side by side. The results file is unchanged and can be re-rendered as many times as you like. ## Where to put the setting `reportgenerator.properties` opens with a banner telling you not to edit it, precisely so an upgrade does not silently revert or re-apply your choices. Put every report override in `user.properties` next to it. That also makes the report configuration a small, reviewable file you can ship with a job rather than a local modification to an installed JMeter. How wide a time window is meaningful for the conclusion you are drawing is a measurement question owned elsewhere; the JMeter half is simply that one property sets the bucket, it defaults to a minute, and it must stay above a second. ## How the value reaches the generator Two files feed the report layer, in this order: `bin/reportgenerator.properties` is loaded first, then the JMeter properties in force are overlaid on top, so anything you set in `user.properties` wins. It is worth noticing which keys the shipped file actually sets and which are only documented in comments: - `jmeter.reportgenerator.overall_granularity=60000` is genuinely set, along with every graph and exporter class name; - `apdex_satisfied_threshold`, `apdex_tolerated_threshold`, `series_filter`, `report_title` and the rest are commented out, so their effective values come from defaults compiled into the report configuration class (500 ms, 1500 ms, an empty filter, and so on). A commented line defines nothing, so grepping the file for a key and finding it does not mean it is set. Either way the override goes in `user.properties`, and the value is applied the next time a report is built.
- Does lowering it also change the Response Time Distribution graph?No. That graph has its own `set_granularity=100` in `reportgenerator.properties` and buckets by response time, not by clock time. Only the over-time family reads `${jmeter.reportgenerator.overall_granularity}`, so the distribution histogram is unaffected by the change.
- What happens if you set the granularity to 500 ms?JMeter accepts it — nothing validates the value — but the documented rule is that the granularity must be above 1000 ms or the throughput graphs will be wrong, because the per-second rate is derived by scaling the bucket total by 1000/granularity. You get graphs that look fine and are not.
saying these in an interview costs you the question
- Says the run must be repeated to change the granularity
- Sets the value below one second
- Edits reportgenerator.properties instead of user.properties
- Thinks the property changes the recorded samples
- Expects it to move the response time distribution graph