Operations 8 min read

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.

FunTester
FunTester
FunTester
How to Add a Soft‑Start Mechanism for High‑QPS Performance Testing in Java

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.

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.

JavaconcurrencyPerformance TestingLoad Testinghigh QPSsoft start
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.