Checkpoint Lab — Timers, Think Time, Pacing, Throughput, and Realistic User Behavior
Build one browse-and-submit journey whose behavioral think time is independent from its scenario-start schedule. Predict thread requirements, run a sufficient profile, then preserve a deliberately under-supplied rate miss.
Learning objectives
- Scope 400 ms think time only to Submit.
- Scope PTT only to Browse/scenario starts.
- Predict concurrency before execution.
- Measure Browse-start RPS separately from total HTTP RPS.
- Compare sufficient and under-supplied thread pools.
- Produce timer, JTL, log, server, generator, timeline, and validity evidence.
1. Assumptions and ceilings
| Item | Baseline |
|---|---|
| JMeter | 5.6.3 |
| Java | Java 17 lab; release requires Java 8+ |
| Plugins | None |
| Target | http://127.0.0.1:8000 only |
| Browse | ~80 ms |
| Submit | ~120 ms |
| Think | 400 ms before Submit only |
| Good profile | 3 threads; PTT 10 Browse starts/10 s; 12 s Thread Group duration |
| Under profile | 1 thread; PTT 20 Browse starts/10 s; 10 s duration |
| Maximum | ≤3 checkpoint threads; ≤12 seconds |
2. Setup and preflight
mkdir -p results/checkpoint-good results/checkpoint-under
python fixtures/timing_fixture.py --log results/checkpoint-good/server-events.jsonl
curl --fail --silent http://127.0.0.1:8000/health
Restart the fixture with a fresh log between profiles.
3. Checkpoint tree
Test Plan
└── Thread Group — profile-specific users/duration
├── Browse — GET /browse
│ └── Precise Throughput Timer
│ throughput/period: profile-specific
│ Test duration: 10 s
│ batch 1, delay 0, seed 4242
└── Submit — POST /submit
└── Constant Timer — 400 ms
This makes the controlled rate population explicit: Browse/scenario starts. Submit is a second HTTP sample generated by each completed scenario.
4. Predict concurrency
Browse 0.080 s + think 0.400 s + Submit 0.120 s ≈ W=0.600 s
Good: λ=1/s → N≈0.60 → arithmetic minimum 1; use 3 for modest headroom
Under: λ=2/s → N≈1.20 → at least 2 predicted; use 1 intentionally
Also predict that sampler p50/p95 stays near service delays while Timer waiting appears in the timeline.
5. Good profile
- 3 threads
- Thread Group duration 12 s
- PTT target 10 / 10 s, PTT Test duration 10 s
- 400 ms Submit Timer
jmeter -n \
-t plans/checkpoint-good.jmx \
-l results/checkpoint-good/results.jtl \
-j results/checkpoint-good/jmeter.log \
-Jjmeter.save.saveservice.print_field_names=true \
-Jjmeter.save.saveservice.thread_counts=true \
-Jsampleresult.timestamp.start=false
python tools/analyze_timing.py results/checkpoint-good/results.jtl
Evaluate the ten-second Browse population rather than demanding exactly one event in every one-second bucket; PTT is randomized.
6. Under-supplied profile
Restart the fixture. Use 1 thread, 10-second duration and PTT target 20 Browse starts / 10 s = 2/s. The estimate requires ~1.2 concurrent users, so one thread is intentionally insufficient.
jmeter -n \
-t plans/checkpoint-under.jmx \
-l results/checkpoint-under/results.jtl \
-j results/checkpoint-under/jmeter.log \
-Jjmeter.save.saveservice.print_field_names=true \
-Jjmeter.save.saveservice.thread_counts=true \
-Jsampleresult.timestamp.start=false
python tools/analyze_timing.py results/checkpoint-under/results.jtl
7. Explain the gap causally
| Evidence | Good profile | Under profile |
|---|---|---|
| Configured Browse target | 1/s | 2/s |
| Thread supply | 3 | 1 |
| Estimated N | ~0.6 | ~1.2 |
| Achieved Browse RPS | Should approach configured population if healthy | Expected below target |
| Endpoint p50/p95 | Near fixture delays | Can remain near fixture delays |
| Target max_active | Low/modest | Can remain low — target need not be the limiter |
| Generator | Should have strong headroom | Still tiny; one user is the bottleneck by design |
8. Annotated timeline
scheduled Browse → [Browse ~80 ms] → [think 400 ms] → [Submit ~120 ms] → next available cycle
sampler elapsed wait sampler elapsed
Use server event timestamps to verify the target only works during Browse/Submit intervals.
9. Generator validity
Record Task Manager/top CPU/memory/network. A saturated
injector invalidates target-capacity conclusions; stop rather than
hiding it with longer Timers or a giant heap.
10. Evidence packet
| Artifact | Required content |
|---|---|
| Good/under JMX | Users, duration, stable labels, Timer types/values/scope. |
| Workload math | W≈0.60 s and N≈λW predictions. |
| JTL | Raw labels/timestamps/elapsed/thread counts. |
jmeter.log |
Engine/timer diagnostics and PTT schedule messages where present. |
| Analyzer | Browse-start RPS, total RPS, p50/p95, active threads, timeline. |
| Server JSONL/stats | Independent path counts/timestamps/max concurrency. |
| Generator note | CPU/memory/network headroom. |
| Validity statement | Configured rate ≠ guaranteed achieved rate; Timer wait ≠ server latency. |
11. Verification checklist
- Loopback target only.
- PTT under Browse only.
- Constant Timer under Submit only.
- Browse-start RPS separate from total HTTP RPS.
- Sampler percentiles separate from think time.
- Under-profile rate miss attributed to thread-supply evidence before target capacity.
-
JTL,
jmeter.log, server events, and miss evidence preserved.
12. Validity statement
N≈λW,
so achieved Browse-start rate fell below target even while endpoint
latency stayed near fixed fixture service times. This demonstrates
Timer scope, thread supply, and configured-versus-achieved rate—not
production capacity.”
13. Cleanup and rollback
- Stop the fixture.
- Keep both evidence sets until review.
- Keep heavy GUI listeners out of load copies.
- No production target, credential, remote engine, plugin, container, database, or system-wide tuning was changed.
14. What Chapter 07 adds
The operating model now has a timing contract: user think distribution, pacing/rate mechanism, exact Timer scope, configured rate population, required thread supply, achieved rate, sampler latency, generator headroom, and target evidence are reviewed separately.
Chapter 08 adds assertions so a paced run must also prove functional correctness.
Knowledge check
Why is PTT attached to Browse only?
The target population is scenario starts. Thread Group scope would pace Submit too.
For λ=2/s and W=0.60 s, what N do you estimate?
About 1.2, so at least 2 threads before measured headroom.
Why can total HTTP RPS be roughly double Browse-start RPS?
Each completed scenario includes Browse and Submit.
What evidence suggests the under-profile miss is not target saturation?
Stable endpoint latency, low target concurrency, healthy generator resources, one busy JMeter thread, and concurrency math predicting ≥2 threads.
What is the bridge to Chapter 08?
Once offered load and timing are valid, assertions must prove responses remain correct under that load.
Official references and version notes
- Elements of a Test Plan — timer scope, additive delays, execution order, and Thread Groups.
- Component Reference — Constant, Uniform Random, Constant Throughput, Precise Throughput, and Open Model behavior.
- Properties Reference — timer.factor and result settings.
- Best Practices — thread sizing, coordinated-omission warning, CLI execution, and lean listeners.
- Getting Started — GUI authoring versus CLI load execution.
- Download Apache JMeter — current production release and Java requirement.
Verified 2026-09-05: Apache JMeter 5.6.3; release requires Java 8+, labs use Java 17; no plugins. Timers run before in-scope samplers and applicable timers add together. Constant/Precise Throughput Timers pace existing threads and cannot guarantee configured throughput if threads, other delays, the generator, or target are limiting. Precise Throughput Timer uses a Poisson-style schedule, and its timer test-duration field is not the Thread Group stop condition. The current Open Model Thread Group is explicitly experimental and is optional only in this chapter.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this
address.