Operations 12 min read

Real‑Time QPS Monitoring and Asynchronous Progress Display for Load Tests

This article explains how to enrich a performance‑testing framework with an asynchronous progress bar that also reports real‑time QPS, detailing the design of a unified Progress class, its handling of different thread models, the QPS calculation logic, a sample Groovy test script, and the resulting console output.

FunTester
FunTester
FunTester
Real‑Time QPS Monitoring and Asynchronous Progress Display for Load Tests

In traditional performance testing the author first saved test data and performed statistics only after the run finished, which reduced runtime resource consumption but prevented monitoring of the test progress, leading to long idle periods. To address this, an asynchronous progress‑display feature was added, inspired by JMeter's sampler that can report QPS in real time.

Unified Progress Class Design

The author initially considered creating a separate asynchronous class but realized the functionality overlapped heavily with the existing progress‑bar class. Consequently, the two were merged into a single generic Progress<F extends ThreadBase> class that implements Runnable. The class records each QPS value in a List<Integer> qs and supports three execution models:

Time‑limited ( ThreadLimitTimeCount) – isTimesMode = false, limit set to the time limit.

Count‑limited ( ThreadLimitTimesCount) – isTimesMode = true, limit set to the iteration count.

Fixed‑QPS ( FixedQpsThread) – canCount = false and the QPS is derived from the fixed request rate.

The init() method inspects the first thread instance to determine which model applies, throwing an exception if none matches. The run() loop sleeps for HttpClientConstant.LOOP_INTERVAL, computes the progress proportion pro, and logs a line such as:

logger.info("{} progress:{}  {}, current QPS: {}", taskDesc,
    getManyString(ONE, (int)(pro * LENGTH)),
    getPercent(pro * 100), getQPS());

The getQPS() method distinguishes between countable and fixed‑QPS modes. In countable mode it extracts the last two latency values from each thread, averages them, and computes QPS as 1000 * threadNum / averageLatency. In fixed‑QPS mode it divides the executed request count by elapsed time. Each computed QPS is appended to qs for later charting.

When the test finishes, stop() sets the running flag to false, logs a final 100% progress line, and calls printQPS(). This method draws a QPS curve using StatisticsUtil.draw(). If the number of recorded points exceeds BUCKET_SIZE, the data is down‑sampled by selecting evenly spaced points.

Sample Test Script

A Groovy script creates ten FunTester instances, each extending ThreadLimitTimesCount<String> with a random sleep of 0.01 + getRandomDouble() in the overridden doing() method. The script then starts a Concurrent runner with the list of threads and a description:

def ts = []
10.times { ts << new FunTester(StringUtil.getString(10), 400) }
new Concurrent(ts, "FunTester test progress sampler").start()

The FunTester class also implements clone() to allow the framework to duplicate the task for each thread.

Console Output and Results

The run produces periodic INFO logs showing the progress bar, percentage, and current QPS, e.g.:

INFO-> FunTester test progress sampler progress:▍▍▍  4.75% , current QPS: 22

After all threads complete, a summary line reports total execution time (≈211 s), total requests (4000), and a final QPS of about 19.4. The QPS curve is rendered as an ASCII chart and saved to a file, with the JSON snapshot of the run included for further analysis.

Key Takeaways

Integrating real‑time QPS reporting into a progress bar provides immediate insight into load‑test dynamics and helps spot bottlenecks early.

Designing the Progress class to handle multiple execution models keeps the solution reusable across different test scenarios.

Collecting per‑thread latency samples enables accurate QPS calculation without external monitoring tools.

The approach remains lightweight, using only standard Java concurrency utilities and simple logging.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavamonitoringPerformance TestingLoad TestingQPSasynchronous progress
FunTester
Written by

FunTester

10k followers, 1k articles | completely useless

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.