How to Micro‑Benchmark API Signature Overhead for Accurate Performance Testing
The article explains how to isolate and measure the time spent on request signature generation in an API performance test using micro‑benchmarks, provides Java and Groovy code examples, and discusses subtracting non‑request overhead to obtain calibrated throughput.
Performance testing of a signed API
When testing an API that requires RSA‑based request signing, the local signature generation can dominate the latency (≈10 ms per request, up to 100 ms under concurrency). To obtain accurate server‑side response times, the signature cost must be measured and subtracted.
Micro‑benchmarking approach
Run the full load test (signature + HTTP request) with a fixed number of threads and iterations.
Run a second benchmark with the same thread/iteration configuration but with the HTTP request disabled, measuring only the data‑preparation and signature steps.
Subtract the second duration from the first to get the net API latency.
Repeat the micro‑benchmark several times to reduce variance.
Signature generation code (Java)
@Override
protected void doing() throws Exception {
String url = com.okayqa.studentapd.base.OkayBase.HOST + "/api/member/createOrRenewMember";
Map<String, String> p = new HashMap<>();
p.put("days", "1");
p.put("memberId", "208");
p.put("orderNo", "F" + RString.getString(4) + i.getAndAdd(1));
p.put("orderPaySystemId", "85123213");
p.put("orderPayTime", "2020-02-09 10:00:00");
p.put("payMoney", "30");
p.put("recordSources", "3");
p.put("renewal", "false");
def user = Users.getStuUser(i.getAndAdd(1) % 1000);
p.put("systemId", user);
String sign = RSAUtilLJT.sign(p, RSAUtilLJT.getPrivateKey(RSAUtilLJT.RSA_PRIVATE_KEY));
p.put("sign", sign);
// HttpPost post = getHttpPost(url, JSON.toJSONString(p));
// ... send request and validate response ...
}Load‑test driver (Groovy)
public static void main(String[] args) {
def argsUtil = new ArgsUtil(args);
def thread = argsUtil.getIntOrdefault(0, 1); // number of concurrent threads
def times = argsUtil.getIntOrdefault(1, 100); // requests per thread
def reqs = [];
thread.times {
reqs << new Thr(times); // Thr encapsulates the doing() method above
}
new Concurrent(reqs, "Member payment and renewal API").start();
testOver();
}Calibration and caveats
The subtraction method assumes that signature generation time is independent of network latency.
Local idle periods between requests introduce artificial wait time; therefore the calibrated throughput may be higher than what the server can sustain under continuous load.
Further refinement (e.g., synchronizing request start times or using a timer that excludes local sleep) is needed to reduce this measurement error.
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.
