Retry flaky relay URL parsing benchmark before failing

Single-shot wall-clock timing can be inverted by JIT compilation
variance and CPU scheduling noise. Retry the measurement up to
3 times (with JIT warmup before each attempt and a short cooldown
between failed attempts) and report per-attempt timings on failure.
This commit is contained in:
greenart7c3
2026-08-19 08:12:55 -03:00
parent 347eb4848c
commit 33221752e2
@@ -172,11 +172,19 @@ class SignerProviderBenchmarkTest {
* java.net.URI.host twice: once for the whitelist check and once for the
* permission lookup. This benchmark measures the cost of that duplication.
*/
/**
* Timing assertions are inherently subject to JIT compilation variance and
* transient CPU scheduling noise, so the measurement is retried a few
* times before declaring failure. Passing on any attempt is enough: it
* demonstrates that parsing the host once is never algorithmically slower
* than parsing it twice.
*/
@Test
fun `benchmark relay url parsing - once is faster than twice`() {
val relayUrl = "wss://relay.example.com/nostr"
val iterations = 100_000
val warmupIterations = 5_000
val maxAttempts = 3
fun extractHost(url: String): String = try {
URI(url).host ?: url
@@ -184,36 +192,51 @@ class SignerProviderBenchmarkTest {
url
}
// Warmup
repeat(warmupIterations) { extractHost(relayUrl) }
// (twiceNs, onceNs) per attempt, kept for the failure message.
val attempts = mutableListOf<Pair<Long, Long>>()
val twiceNs = measureNanoTime {
repeat(iterations) {
// Old: host extracted in two separate blocks.
val forWhitelist = extractHost(relayUrl)
val forPermission = extractHost(relayUrl)
check(forWhitelist == forPermission)
for (attempt in 1..maxAttempts) {
// Warmup before every attempt so JIT state does not carry over bias.
repeat(warmupIterations) { extractHost(relayUrl) }
val twiceNs = measureNanoTime {
repeat(iterations) {
// Old: host extracted in two separate blocks.
val forWhitelist = extractHost(relayUrl)
val forPermission = extractHost(relayUrl)
check(forWhitelist == forPermission)
}
}
val onceNs = measureNanoTime {
repeat(iterations) {
// New: extracted once, shared between whitelist and permission check.
val relayHost = extractHost(relayUrl)
check(relayHost == relayHost)
}
}
attempts += twiceNs to onceNs
println(
"[Benchmark] relay host parse (attempt $attempt/$maxAttempts): " +
"twice=${twiceNs / 1_000_000}ms " +
"once=${onceNs / 1_000_000}ms " +
"speedup=${"%.2f".format(twiceNs.toDouble() / onceNs)}x",
)
if (onceNs <= twiceNs) return
// Let the machine settle briefly so the next attempt is not
// polluted by whichever background task skewed this one.
if (attempt < maxAttempts) Thread.sleep(100)
}
val onceNs = measureNanoTime {
repeat(iterations) {
// New: extracted once, shared between whitelist and permission check.
val relayHost = extractHost(relayUrl)
check(relayHost == relayHost)
}
}
val speedup = twiceNs.toDouble() / onceNs
println(
"[Benchmark] relay host parse: " +
"twice=${twiceNs / 1_000_000}ms " +
"once=${onceNs / 1_000_000}ms " +
"speedup=${"%.2f".format(speedup)}x",
)
assertTrue(
"Parsing relay host once should be at least as fast as twice (speedup=${"%.2f".format(speedup)}x)",
onceNs <= twiceNs,
"Parsing relay host once should be at least as fast as twice " +
"(attempts: ${attempts.joinToString { (twiceNs, onceNs) ->
"twice=${twiceNs / 1_000_000}ms once=${onceNs / 1_000_000}ms"
}})",
attempts.any { (twiceNs, onceNs) -> onceNs <= twiceNs },
)
}