How to Add a Soft‑Start Mechanism for High‑QPS Performance Testing in Java
This article explains the concept of soft‑start in performance testing, presents Java implementations for both fixed‑thread and fixed‑QPS models, discusses error‑impact considerations, and provides practical code snippets to gradually ramp up load and improve measurement accuracy for high‑throughput services.
Soft‑Start Concept
Soft‑start, originally a motor‑control term, describes a gradual increase of voltage to avoid shock; in performance testing it means slowly ramping up request generation to prevent a sudden spike in load.
Fixed‑Thread Model Implementation
The simplest approach adds a start‑up interval between thread launches, similar to JMeter's technique.
/**
* Performance test start‑up time (seconds)
*/
public static double RUNUP_TIME = 30.0;In com.funtester.frame.execute.Concurrent#start the launch loop is modified to insert a sleep based on RUNUP_TIME:
startTime = Time.getTimeStamp();
for (int i = 0; i < threadNum; i++) {
ThreadBase thread = threads.get(i);
if (StringUtils.isBlank(thread.threadName))
thread.threadName = StatisticsUtil.getTrueName(desc) + i;
thread.setCountDownLatch(countDownLatch);
sleep(RUNUP_TIME / threadNum);
executorService.execute(thread);
}
shutdownService(executorService, countDownLatch);
endTime = Time.getTimeStamp();During test cases the run‑up time can be overridden, e.g.:
Constant.RUNUP_TIME = util.getIntOrdefault(2, 30);Fixed‑QPS Model Implementation
For a target QPS (e.g., 5000 req/s) the algorithm linearly stretches a short warm‑up period (default 10 s) to a longer ramp‑up (default 30 s). The interval between requests is computed, then each request’s delay is adjusted to gradually increase QPS.
interval = 1_000_000_000 / qps; // 1 s = 1 000 ms, 1 ms = 1 000 000 ns
int runupTotal = qps * PREFIX_RUN; // total requests during ramp‑up
double diffTime = 2 * (Constant.RUNUP_TIME / PREFIX_RUN * interval - interval);
double piece = diffTime / runupTotal; // incremental time per request
for (int i = runupTotal; i > 0; i--) {
executorService.execute(threads.get(limit-- % queueLength).clone());
sleep((long) (interval + i * piece));
}
logger.info("Warm‑up complete, start testing!");Error Impact and Mitigation
Soft‑start influences performance‑test metrics, potentially inflating error rates. To mitigate, reset counters after the warm‑up phase before the main measurement begins.
In the fixed‑thread model this is done by pausing after the warm‑up, clearing counters, and then resuming full‑load execution:
for (int i = 0; i < threadNum; i++) {
ThreadBase thread = threads.get(i);
if (StringUtils.isBlank(thread.threadName))
thread.threadName = StatisticsUtil.getTrueName(desc) + i;
thread.setCountDownLatch(countDownLatch);
sleep(RUNUP_TIME / threadNum);
executorService.execute(thread);
}
sleep(1.0);
ThreadBase.stop();
try {
countDownLatch.await();
} catch (InterruptedException e) {
FailException.fail("Soft‑start performance test failed!");
}
threads.forEach(f -> f.initBase());
logger.info("Warm‑up complete, start testing!");
countDownLatch = new CountDownLatch(threadNum);The initBase method clears execution counters and temporary data structures:
/**
* Clear stored lists after object copy
*/
public void initBase() {
this.executeNum = 0;
this.errorNum = 0;
this.costs = new ArrayList<>();
this.marks = new ArrayList<>();
}Additional Notes
The implementation deliberately avoids using CyclicBarrier or Phaser because, in a fixed‑thread scenario, they can introduce unwanted synchronization issues.
Empirical observations show that the actual QPS measured aligns more closely with the average response‑time based calculation rather than the theoretical QPS2 metric.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
