Skip to content

Process Log Pipeline Benchmark (2026-09-19)

This report records the first synchronous-versus-asynchronous process-log comparison required by the log system architecture. It reports the median of three trials. It is still a development-host measurement rather than a portable service-level guarantee.

Environment

  • Commit: 4dbeb59e8726735c2ec8f55ef5ba86e74603fa3d
  • Candidate: the working tree on feat/async-process-logging
  • OS: Linux 6.14.0-1015-nvidia, ARM64
  • Logical CPUs: 20
  • File descriptor limit: 500,000
  • Rust: 1.97.1
  • Build: release profile
  • Workload: 32 keep-alive connections, 2-second warmup, 10-second measured window, local mock LLM backend with a 1 ms fixed response delay
  • Throttled sink: 4,096 bytes per second
  • Trials: 3 per variant and sink; the table reports their medians

The synchronous binary was built from the commit above in a detached worktree. The asynchronous binary was built from the working branch. Both used the same lockfile, release profile, profile JSON, mock backend, and load driver.

Results

Sink Variant RPS p95 p99 Errors Error rate Peak RSS
Fast Synchronous 9,663.8 4.493 ms 5.316 ms 0 0% 38.770 MiB
Fast Asynchronous 9,945.0 4.322 ms 5.354 ms 0 0% 39.324 MiB
Throttled Synchronous 16.0 n/a n/a 160 100% 19.090 MiB
Throttled Asynchronous 9,918.3 4.524 ms 5.525 ms 0 0% 42.152 MiB
Stalled Synchronous 16.0 n/a n/a 160 100% 18.813 MiB
Stalled Asynchronous 9,825.4 4.539 ms 5.638 ms 0 0% 42.797 MiB

With a fast sink, the asynchronous candidate delivered 2.9% more requests per second and reduced p95 latency by 3.8% in this run. Under throttled and stalled sinks, every measured synchronous request failed after the process pipe filled, while the asynchronous candidate retained roughly 9,825–9,918 RPS with zero request failures. Latency percentiles for the failed synchronous cases are intentionally reported as unavailable rather than as zero.

The higher RSS shown for the successful asynchronous overload cases is not a like-for-like service-capacity comparison: the synchronous process stopped making request progress before reaching its normal steady-state allocation. The asynchronous queue itself remains capped at 8,192 records and 16 MiB of retained payload with the default configuration.

Rerun after configurable queue limits

After logging.queue_capacity and logging.queue_capacity_bytes were wired through the startup path, the same binaries, workload, sink rates, and three-trial median procedure were run again. The candidate used the default 8,192-record and 16 MiB settings.

Sink Variant RPS p95 p99 Errors Error rate Peak RSS
Fast Synchronous 9,889.8 4.224 ms 5.342 ms 0 0% 39.180 MiB
Fast Asynchronous 9,514.4 4.558 ms 5.470 ms 0 0% 38.969 MiB
Throttled Synchronous 16.0 n/a n/a 160 100% 19.563 MiB
Throttled Asynchronous 9,850.4 4.599 ms 5.715 ms 0 0% 42.246 MiB
Stalled Synchronous 16.0 n/a n/a 160 100% 18.813 MiB
Stalled Asynchronous 9,809.5 4.554 ms 5.610 ms 0 0% 42.695 MiB

On the fast sink, the candidate was 3.8% lower in throughput and 7.9% higher in p95 latency than the synchronous baseline, within the 10% regression budget. Under throttled and stalled sinks it again completed with zero errors at 103.5% and 103.1% of its own fast-sink throughput, while every measured synchronous request failed. All comparison gates passed.

Initial regression budget

Until the scheduled runner accumulates a longer history, the review budget for this implementation is:

  • the fast-sink median must not regress by more than 10% in either throughput or p95 latency against the synchronous baseline;
  • throttled and stalled candidates must complete with zero request failures;
  • throttled and stalled throughput must remain at least 80% of the candidate's own fast-sink throughput; and
  • queue depth must never exceed 8,192 records, retained queue payload must never exceed 16 MiB, and an individual formatted record must never exceed 64 KiB.

These bounds deliberately leave room for shared-host variance while rejecting the failure mode this change exists to remove. Replace them with runner-specific thresholds after repeated scheduled measurements establish dispersion.

Reproduction

Build one binary from the synchronous baseline and one from the candidate, then run:

TRIALS=3 perf/compare-log-pipeline.sh \
  /path/to/synchronous/continuum-router \
  /path/to/asynchronous/continuum-router

The harness writes the six machine-readable result files and a generated Markdown comparison below perf/results/log-pipeline/. That directory is git-ignored because repeated local and scheduled measurements are runtime artifacts; this checked-in report records the reviewed reference run.