In JMeter's Backend Listener, what happens when the Async Queue size is exhausted?
answer
- Nothing is thrown away here
- The producer waits for the consumer
- Evidence arrives only after the run
- Five thousand entries by default
basics
~10 sThe sampling thread that produced the result blocks until the worker frees a slot. Nothing is dropped; the delay lands on the test thread, and JMeter logs a queue-wait warning once the test ends.
solid answer
~40 s`BackendListener.sampleOccurred` first tries `queue.offer(sr)` on an `ArrayBlockingQueue` sized by the **Async Queue size** field (`QUEUE_SIZE`, default `5000`). If that fails it counts a queue wait and calls the blocking `queue.put(sr)`, so the JMeter thread that just finished a sample stalls until the background worker drains an entry. Results are therefore never silently discarded - the cost is paid by the generator. Note what it is not: the sample's elapsed time was recorded before the listener saw it, so streamed response times are not inflated by the wait; what falls is achieved throughput, because the thread cannot start its next iteration. JMeter accumulates `queueWaits` and `queueWaitTime` in nanoseconds and logs a warning naming both at test end.
go deeper
Know the Backend Listener has a queue between the test threads and its worker thread, and that its size is a field on the element with a default of 5000.
Explain the offer-then-put sequence: a full queue makes the sampling thread block rather than lose a result, and JMeter records how often that happened and for how long.
Diagnose it. An achieved rate that sags together with a queue-wait warning in jmeter.log at test end points at the listener's worker rather than at the system under test - and note it does not point at the metrics store, whose latency never reaches this queue.
Take a position on a listener that can throttle the generator: queue sizing, whether a metrics store belongs on the critical path of a run at all, and what happens to the run when it is unreachable.
## Offer first, then block The Backend Listener puts an `ArrayBlockingQueue` between the sampling threads and the single worker thread that feeds the client. With the shipped Graphite and InfluxDB clients that worker only aggregates into memory; a separate scheduled thread does the transmitting. The queue's capacity is the **Async Queue size** field on the element (`QUEUE_SIZE` in the `.jmx`), default `5000`. When a sample finishes, the listener runs: 1. `queue.offer(sr)` - the non-blocking attempt. Normally it succeeds and the thread moves on. 2. If it returns false, increment a `queueWaits` counter, take a nanosecond timestamp, then call `queue.put(sr)` - the **blocking** form. 3. Timestamp again and add the elapsed nanoseconds to `queueWaitTime`. `put` returns only when the worker has drained an entry. So the JMeter thread that just completed a sample is parked inside the listener until the worker catches up. ## Nothing is dropped, and that is the point Two mistakes are equally common and equally wrong: that the oldest queued results are evicted, and that new ones are discarded. Neither happens. The queue is a hard back-pressure boundary, so every result eventually reaches the client. What gives way instead is the **generator**. The distortion is specific, and worth stating precisely: the sample's own elapsed time was recorded before the listener ever saw the result, so the response times you stream are not inflated by the wait. What suffers is throughput - the thread cannot begin its next iteration until the queue accepts the result. On a long soak this shows up as an achieved rate that sags when the worker falls behind the sample rate, which is easy to misread as the system under test wobbling. Note what it is *not*: the metrics store's own latency never reaches this queue, because the flush runs on the client's scheduled thread — outside the lock the worker needs for Graphite, and as an asynchronous HTTP submit for InfluxDB. ## Where the evidence is At test end, and only if `queueWaits` is above zero, JMeter logs a warning: ``` QueueWaits: 412; QueueWaitTime: 1839221004 (nanoseconds), you may need to increase queue capacity, see property 'backend_queue_capacity' ``` Two things to know about that message: - It is written **once, at the end**, at `WARN` level to `jmeter.log`. There is no live metric for it, so the dashboard the listener feeds will never show you that the listener itself was the bottleneck. Checking for it is a post-run step. - The property it names, `backend_queue_capacity`, **does not exist** anywhere else in JMeter 6.0.0 - the queue size is read from the element's own `QUEUE_SIZE` property and nothing else. The message is stale; the field in the GUI is the real knob. An invalid value there is logged and replaced with the default 5000 rather than failing the run. ## Sizing it There is no formula worth memorising, because the queue only matters when the worker cannot keep up. Reach for a larger value when the warning appears and the overrun is bursty - a bigger buffer rides out a burst. Do not reach for it when the worker is simply slower than the run's sample rate on average, because no finite queue absorbs a permanent deficit; that is a signal to give the worker less to do per result, by turning `summaryOnly` on or narrowing the sampler filter so fewer per-label metrics are updated. What a larger queue costs the injector in memory is a plan-cost question rather than a listener-configuration one.
- Does a full Backend Listener queue lose sample results?No. The failed offer is followed by a blocking put, so every result eventually reaches the worker and the streamed series has no gaps. What you lose is generator throughput while threads wait, which surfaces as a lower achieved rate rather than as missing points on the graph.
- Where would you see evidence that a Backend Listener's queue filled during a run?In `jmeter.log` at the end of the run. JMeter logs a WARN line carrying `QueueWaits` and `QueueWaitTime` in nanoseconds, and only when the counter is above zero. There is no live metric for it, so the check is a post-run log grep rather than something the dashboard shows.
saying these in an interview costs you the question
- Says the oldest queued results are evicted
- Says new results are discarded until space frees
- Thinks recorded response times are inflated by the wait
- Assumes the queue is unbounded by default
- Trusts the warning's property name literally