@@ -80,6 +80,9 @@ proc runThroughputBenchmark*[Q](
8080
8181 # Start timing. Monotonic clock — `epochTime` (wall clock) can step
8282 # backward across NTP adjustments and skew throughput numbers.
83+ # Nanosecond precision: ms-precision buckets multiple short runs into
84+ # the same integer ms, producing identical samples and stddev=0 on a
85+ # fast CI runner. ops/ms is reconstructed as a float at print time.
8386 let startTime = getMonoTime ()
8487
8588 # Launch threads
@@ -94,8 +97,8 @@ proc runThroughputBenchmark*[Q](
9497 for i in 0 ..< numConsumers:
9598 joinThread (consumerThreads[i])
9699
97- let elapsedMs = float (inMilliseconds (getMonoTime () - startTime))
98- result = float (messageCount) / elapsedMs
100+ let elapsedNs = float (inNanoseconds (getMonoTime () - startTime))
101+ result = float (messageCount) * 1_000_000.0 / elapsedNs
99102
100103proc benchmarkThroughput * [Q](
101104 initQueue: proc (): Q,
@@ -185,6 +188,7 @@ proc runMupmucBenchmark[N, P, C: static int, T](
185188
186189 # Start timing. Monotonic clock — `epochTime` (wall clock) can step
187190 # backward across NTP adjustments and skew throughput numbers.
191+ # See runThroughputBenchmark for the nanosecond-precision rationale.
188192 let startTime = getMonoTime ()
189193
190194 # Launch threads
@@ -199,8 +203,8 @@ proc runMupmucBenchmark[N, P, C: static int, T](
199203 for i in 0 ..< C:
200204 joinThread (consumerThreads[i])
201205
202- let elapsedMs = float (inMilliseconds (getMonoTime () - startTime))
203- result = float (messageCount) / elapsedMs
206+ let elapsedNs = float (inNanoseconds (getMonoTime () - startTime))
207+ result = float (messageCount) * 1_000_000.0 / elapsedNs
204208
205209# Fixed-size Mupmuc benchmark functions for common thread counts
206210proc benchmarkMupmuc1P1C * (
@@ -355,8 +359,8 @@ proc runUnboundedMupsicBenchmark[S: static int, T; MaxThreads: static int](
355359 joinThread (producerThreads[i])
356360 joinThread (consumerThread)
357361
358- let elapsedMs = float (inMilliseconds (getMonoTime () - startTime))
359- result = float (totalMessages) / elapsedMs
362+ let elapsedNs = float (inNanoseconds (getMonoTime () - startTime))
363+ result = float (totalMessages) * 1_000_000.0 / elapsedNs
360364
361365proc benchmarkUnboundedMupsicNP1C (
362366 numProducers: int ,
@@ -446,8 +450,8 @@ when isMainModule:
446450 numConsumers = 1 ,
447451 runs = 10 ,
448452 )
449- echo fmt" mean: { sipsicMetrics.mean:.0f } ops/ms "
450- echo fmt" stddev: { sipsicMetrics.stddev:.0f } "
453+ echo fmt" mean: { sipsicMetrics.mean:.1f } ops/ms "
454+ echo fmt" stddev: { sipsicMetrics.stddev:.1f } "
451455 echo " "
452456
453457 # Mupmuc (bounded MPMC)
@@ -464,8 +468,8 @@ when isMainModule:
464468 benchmarkMupmuc4P4C (runs = 10 )
465469 else :
466470 ThroughputMetrics ()
467- echo fmt" mean: { metrics.mean:.0f } ops/ms "
468- echo fmt" stddev: { metrics.stddev:.0f } "
471+ echo fmt" mean: { metrics.mean:.1f } ops/ms "
472+ echo fmt" stddev: { metrics.stddev:.1f } "
469473 echo " "
470474
471475 # UnboundedMupsic (unbounded MPSC) — new harness, 33 runs.
@@ -485,9 +489,9 @@ when isMainModule:
485489 benchmarkUnboundedMupsic4P1C ()
486490 else :
487491 ThroughputMetrics ()
488- echo fmt" mean: { metrics.mean:.0f } ops/ms "
489- echo fmt" min: { metrics.min:.0f } max: { metrics.max:.0f } "
490- echo fmt" stddev: { metrics.stddev:.0f } "
492+ echo fmt" mean: { metrics.mean:.1f } ops/ms "
493+ echo fmt" min: { metrics.min:.1f } max: { metrics.max:.1f } "
494+ echo fmt" stddev: { metrics.stddev:.1f } "
491495 echo " "
492496 echo " ==================================================="
493497 echo " "
@@ -503,6 +507,6 @@ when isMainModule:
503507 numConsumers = threads,
504508 runs = 10 ,
505509 )
506- echo fmt" mean: { metrics.mean:.0f } ops/ms "
507- echo fmt" stddev: { metrics.stddev:.0f } "
510+ echo fmt" mean: { metrics.mean:.1f } ops/ms "
511+ echo fmt" stddev: { metrics.stddev:.1f } "
508512 echo " "
0 commit comments