Chapter 07Lesson 05~210 minutes

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.

CheckpointScenario-start RPSN≈λWActive threadsEvidence packet

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
Abort: external target, threads >3, duration >12 s, unresolved inputs, unexpected 5xx, or unsafe generator pressure.

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

Example: “With JMeter 5.6.3/Java 17 against a loopback fixture, PTT scoped to Browse scheduled scenario starts while a 400 ms Constant Timer scoped to Submit modeled user think time. Three threads supplied the low 1/s schedule; one thread was intentionally insufficient for 2/s according to 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

  1. Stop the fixture.
  2. Keep both evidence sets until review.
  3. Keep heavy GUI listeners out of load copies.
  4. 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?

For λ=2/s and W=0.60 s, what N do you estimate?

Why can total HTTP RPS be roughly double Browse-start RPS?

What evidence suggests the under-profile miss is not target saturation?

What is the bridge to Chapter 08?

Next chapter

Assertions and Functional Correctness Under Load

Chapter 08 adds correctness checks so low latency cannot hide wrong responses.

Official references and version notes

Version and compatibility note

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.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0 Send only Ethereum/ERC-20 compatible assets to this address.