74 Benchmarks
trev edited this page 2026-07-15 23:50:11 -04:00

Benchmarks

This is a directional preview, not a release-grade benchmark or a claim that either transport is universally faster. It compares same-language implementations of the same bounded application workload through a reproducible single-host regional-WAN profile: TrevRPC's native protocol over QUIC versus gRPC over HTTP/2 over TCP. Both stacks used TLS with a generated private CA and verified server identity.

The Rust benchmark controller placed each client and server in separate Linux network namespaces connected by a direct veth pair. Both directions applied 15 ms delay with 2 ms jitter, 0.1% random packet loss, a 100 Mbit/s rate, a 1,000-packet queue, and MTU 1500. This produces approximately 30 ms baseline RTT, but it remains synthetic network emulation rather than a physical WAN.

Connection establishment, one validation RPC, and a 1-second warmup preceded each measurement. Protobuf serialization, deserialization, request construction, response validation, and terminal-status handling remained inside each measured operation.

Headline Results

At concurrency 4, TrevRPC recorded higher median throughput in 17 of the 24 same-language, same-shape comparisons and lower median p99 in 17. It won both metrics in 15 comparisons. The largest throughput gains were JavaScript client streaming at 2.94x, JavaScript server streaming at 2.85x, and JavaScript bidirectional streaming at 2.56x. Go gRPC remained materially faster for all streaming shapes; TrevRPC's largest regression was Go client streaming at 0.59x gRPC throughput.

Unary throughput was mostly network-bound and near parity. Ratios near parity are not conclusive given the short runs and observed variability. The table reports direct ratios of independently aggregated medians; a throughput ratio above 1 favors TrevRPC and lower p99 is better.

Latency values are upper bounds of approximately 0.1%-precision log-linear histogram buckets. Their three decimal places preserve the benchmark's nanosecond bucket representation; they do not imply exact nanosecond observations.

Shape Language TrevRPC ops/s gRPC ops/s TrevRPC / gRPC TrevRPC p99 us gRPC p99 us
Unary C 124.2 122.4 1.01x 34734.079 34603.007
Unary C++ 126.0 128.8 0.98x 34078.719 34340.863
Unary Go 126.0 124.8 1.01x 33947.647 34209.791
Unary JavaScript 96.6 118.4 0.82x 64421.887 39649.279
Unary Kotlin 121.0 119.8 1.01x 35782.655 38404.095
Unary Rust 128.4 120.2 1.07x 33882.111 63111.167
Client stream C 60.0 70.8 0.85x 98566.143 97648.639
Client stream C++ 110.4 69.2 1.60x 66191.359 101056.511
Client stream Go 55.2 93.2 0.59x 132644.863 76808.191
Client stream JavaScript 90.0 30.6 2.94x 73924.607 163839.999
Client stream Kotlin 97.4 96.4 1.01x 73662.463 72613.887
Client stream Rust 106.4 87.0 1.22x 50659.327 77725.695
Server stream C 60.2 73.2 0.82x 97910.783 100532.223
Server stream C++ 111.4 59.2 1.88x 67043.327 111017.983
Server stream Go 59.6 100.0 0.60x 115605.503 70778.879
Server stream JavaScript 84.4 29.6 2.85x 67764.223 165150.719
Server stream Kotlin 99.4 89.2 1.11x 72613.887 87031.807
Server stream Rust 110.8 96.8 1.14x 47906.815 69468.159
Bidi C 56.6 53.4 1.06x 103809.023 137625.599
Bidi C++ 101.2 51.6 1.96x 72089.599 115081.215
Bidi Go 49.2 74.0 0.66x 134086.655 85983.231
Bidi JavaScript 72.8 28.4 2.56x 98303.999 206045.183
Bidi Kotlin 57.0 54.2 1.05x 119799.807 120586.239
Bidi Rust 91.2 63.4 1.44x 77856.767 106299.391

The charts show absolute concurrency-4 medians. TrevRPC is blue and gRPC is orange. Each RPC shape uses its own scale.

Throughput

---
config:
  themeVariables:
    xyChart:
      plotColorPalette: '#0ea5e9, #f97316'
  themeCSS: |
    .bar-plot-1 rect {
      transform-box: fill-box;
      transform-origin: center;
      transform: scaleX(0.55);
    }
---
xychart-beta
  title "Unary median throughput at concurrency 4"
  x-axis ["C", "C++", "Go", "JS", "Kotlin", "Rust"]
  y-axis "operations/s" 0 --> 140
  bar "TrevRPC" [124.2, 126.0, 126.0, 96.6, 121.0, 128.4]
  bar "gRPC" [122.4, 128.8, 124.8, 118.4, 119.8, 120.2]
---
config:
  themeVariables:
    xyChart:
      plotColorPalette: '#0ea5e9, #f97316'
  themeCSS: |
    .bar-plot-1 rect {
      transform-box: fill-box;
      transform-origin: center;
      transform: scaleX(0.55);
    }
---
xychart-beta
  title "Client-stream median throughput at concurrency 4"
  x-axis ["C", "C++", "Go", "JS", "Kotlin", "Rust"]
  y-axis "operations/s" 0 --> 120
  bar "TrevRPC" [60.0, 110.4, 55.2, 90.0, 97.4, 106.4]
  bar "gRPC" [70.8, 69.2, 93.2, 30.6, 96.4, 87.0]
---
config:
  themeVariables:
    xyChart:
      plotColorPalette: '#0ea5e9, #f97316'
  themeCSS: |
    .bar-plot-1 rect {
      transform-box: fill-box;
      transform-origin: center;
      transform: scaleX(0.55);
    }
---
xychart-beta
  title "Server-stream median throughput at concurrency 4"
  x-axis ["C", "C++", "Go", "JS", "Kotlin", "Rust"]
  y-axis "operations/s" 0 --> 120
  bar "TrevRPC" [60.2, 111.4, 59.6, 84.4, 99.4, 110.8]
  bar "gRPC" [73.2, 59.2, 100.0, 29.6, 89.2, 96.8]
---
config:
  themeVariables:
    xyChart:
      plotColorPalette: '#0ea5e9, #f97316'
  themeCSS: |
    .bar-plot-1 rect {
      transform-box: fill-box;
      transform-origin: center;
      transform: scaleX(0.55);
    }
---
xychart-beta
  title "Bidirectional median throughput at concurrency 4"
  x-axis ["C", "C++", "Go", "JS", "Kotlin", "Rust"]
  y-axis "operations/s" 0 --> 110
  bar "TrevRPC" [56.6, 101.2, 49.2, 72.8, 57.0, 91.2]
  bar "gRPC" [53.4, 51.6, 74.0, 28.4, 54.2, 63.4]

Application Message Rates

The controller records request and response application-message rates separately. Unary has one request and one response per operation, client streaming has 128 requests and one summary response, server streaming has one request and 128 responses, and bidirectional streaming has 128 requests and 128 responses. These are protobuf application-message rates, not payload-byte or on-wire throughput.

---
config:
  themeVariables:
    xyChart:
      plotColorPalette: '#0ea5e9, #f97316'
  themeCSS: |
    .bar-plot-1 rect {
      transform-box: fill-box;
      transform-origin: center;
      transform: scaleX(0.55);
    }
---
xychart-beta
  title "Unary median request and response message rate at concurrency 4"
  x-axis ["C", "C++", "Go", "JS", "Kotlin", "Rust"]
  y-axis "messages/s in each direction" 0 --> 140
  bar "TrevRPC" [124.2, 126.0, 126.0, 96.6, 121.0, 128.4]
  bar "gRPC" [122.4, 128.8, 124.8, 118.4, 119.8, 120.2]
---
config:
  themeVariables:
    xyChart:
      plotColorPalette: '#0ea5e9, #f97316'
  themeCSS: |
    .bar-plot-1 rect {
      transform-box: fill-box;
      transform-origin: center;
      transform: scaleX(0.55);
    }
---
xychart-beta
  title "Client-stream median request message rate at concurrency 4"
  x-axis ["C", "C++", "Go", "JS", "Kotlin", "Rust"]
  y-axis "request messages/s" 0 --> 15000
  bar "TrevRPC" [7680.0, 14131.2, 7065.6, 11520.0, 12467.2, 13619.2]
  bar "gRPC" [9062.4, 8857.6, 11929.6, 3916.8, 12339.2, 11136.0]
---
config:
  themeVariables:
    xyChart:
      plotColorPalette: '#0ea5e9, #f97316'
  themeCSS: |
    .bar-plot-1 rect {
      transform-box: fill-box;
      transform-origin: center;
      transform: scaleX(0.55);
    }
---
xychart-beta
  title "Server-stream median response message rate at concurrency 4"
  x-axis ["C", "C++", "Go", "JS", "Kotlin", "Rust"]
  y-axis "response messages/s" 0 --> 15000
  bar "TrevRPC" [7705.6, 14259.2, 7628.8, 10803.2, 12723.2, 14182.4]
  bar "gRPC" [9369.6, 7577.6, 12800.0, 3788.8, 11417.6, 12390.4]
---
config:
  themeVariables:
    xyChart:
      plotColorPalette: '#0ea5e9, #f97316'
  themeCSS: |
    .bar-plot-1 rect {
      transform-box: fill-box;
      transform-origin: center;
      transform: scaleX(0.55);
    }
---
xychart-beta
  title "Bidirectional median request and response message rate at concurrency 4"
  x-axis ["C", "C++", "Go", "JS", "Kotlin", "Rust"]
  y-axis "messages/s in each direction" 0 --> 14000
  bar "TrevRPC" [7244.8, 12953.6, 6297.6, 9318.4, 7296.0, 11673.6]
  bar "gRPC" [6835.2, 6604.8, 9472.0, 3635.2, 6937.6, 8115.2]

p99 Latency

---
config:
  themeVariables:
    xyChart:
      plotColorPalette: '#0ea5e9, #f97316'
  themeCSS: |
    .bar-plot-1 rect {
      transform-box: fill-box;
      transform-origin: center;
      transform: scaleX(0.55);
    }
---
xychart-beta
  title "Unary median p99 latency at concurrency 4"
  x-axis ["C", "C++", "Go", "JS", "Kotlin", "Rust"]
  y-axis "microseconds" 0 --> 70000
  bar "TrevRPC" [34734.079, 34078.719, 33947.647, 64421.887, 35782.655, 33882.111]
  bar "gRPC" [34603.007, 34340.863, 34209.791, 39649.279, 38404.095, 63111.167]
---
config:
  themeVariables:
    xyChart:
      plotColorPalette: '#0ea5e9, #f97316'
  themeCSS: |
    .bar-plot-1 rect {
      transform-box: fill-box;
      transform-origin: center;
      transform: scaleX(0.55);
    }
---
xychart-beta
  title "Client-stream median p99 latency at concurrency 4"
  x-axis ["C", "C++", "Go", "JS", "Kotlin", "Rust"]
  y-axis "microseconds" 0 --> 180000
  bar "TrevRPC" [98566.143, 66191.359, 132644.863, 73924.607, 73662.463, 50659.327]
  bar "gRPC" [97648.639, 101056.511, 76808.191, 163839.999, 72613.887, 77725.695]
---
config:
  themeVariables:
    xyChart:
      plotColorPalette: '#0ea5e9, #f97316'
  themeCSS: |
    .bar-plot-1 rect {
      transform-box: fill-box;
      transform-origin: center;
      transform: scaleX(0.55);
    }
---
xychart-beta
  title "Server-stream median p99 latency at concurrency 4"
  x-axis ["C", "C++", "Go", "JS", "Kotlin", "Rust"]
  y-axis "microseconds" 0 --> 180000
  bar "TrevRPC" [97910.783, 67043.327, 115605.503, 67764.223, 72613.887, 47906.815]
  bar "gRPC" [100532.223, 111017.983, 70778.879, 165150.719, 87031.807, 69468.159]
---
config:
  themeVariables:
    xyChart:
      plotColorPalette: '#0ea5e9, #f97316'
  themeCSS: |
    .bar-plot-1 rect {
      transform-box: fill-box;
      transform-origin: center;
      transform: scaleX(0.55);
    }
---
xychart-beta
  title "Bidirectional median p99 latency at concurrency 4"
  x-axis ["C", "C++", "Go", "JS", "Kotlin", "Rust"]
  y-axis "microseconds" 0 --> 220000
  bar "TrevRPC" [103809.023, 72089.599, 134086.655, 98303.999, 119799.807, 77856.767]
  bar "gRPC" [137625.599, 115081.215, 85983.231, 206045.183, 120586.239, 106299.391]

Detailed Results

Every value below is the median of three final samples. Latency and CPU are microseconds; peak RSS is MiB. Throughput is complete RPC operations per second during the fixed admission window. Each streaming operation contains 128 application messages, so operations per second must not be compared across shapes as equal units of work.

Language Stack Shape c Runs p50 us p99 us ops/s Client CPU us/op Server CPU us/op Client peak MiB Server peak MiB
C TrevRPC Unary 1 3 31588.351 34406.399 31.6 188.679 2645.161 21.51 22.94
C gRPC Unary 1 3 32178.175 34406.399 31.2 666.667 533.333 28.14 31.21
C TrevRPC Unary 4 3 32374.783 34734.079 124.2 96.618 1594.203 21.62 23.50
C gRPC Unary 4 3 32735.231 34603.007 122.4 336.134 308.943 28.64 32.60
C++ TrevRPC Unary 1 3 31653.887 33947.647 31.8 187.500 509.554 24.51 24.82
C++ gRPC Unary 1 3 30670.847 34275.327 32.6 613.497 429.448 31.30 31.64
C++ TrevRPC Unary 4 3 31916.031 34078.719 126.0 95.694 300.633 24.48 24.89
C++ gRPC Unary 4 3 31064.063 34340.863 128.8 295.490 232.919 31.76 32.13
Go TrevRPC Unary 1 3 31522.815 34144.255 31.8 437.500 437.500 17.16 17.87
Go gRPC Unary 1 3 31948.799 34144.255 31.4 318.471 268.456 16.98 16.68
Go TrevRPC Unary 4 3 31850.495 33947.647 126.0 237.342 237.342 19.74 20.69
Go gRPC Unary 4 3 32374.783 34209.791 124.8 129.032 128.205 19.29 19.13
JavaScript TrevRPC Unary 1 3 31621.119 34406.399 31.8 632.911 880.503 78.57 78.19
JavaScript gRPC Unary 1 3 32735.231 35651.583 30.4 1390.728 980.392 84.70 82.08
JavaScript TrevRPC Unary 4 3 39059.455 64421.887 96.6 391.753 639.175 81.89 81.97
JavaScript gRPC Unary 4 3 33685.503 39649.279 118.4 721.477 392.857 112.84 101.68
Kotlin TrevRPC Unary 1 3 33390.591 35717.119 30.2 3841.060 3774.834 131.25 142.99
Kotlin gRPC Unary 1 3 32964.607 36765.695 30.4 3486.842 3157.895 144.67 152.93
Kotlin TrevRPC Unary 4 3 33226.751 35782.655 121.0 1824.212 1669.421 134.91 147.38
Kotlin gRPC Unary 4 3 33161.215 38404.095 119.8 1803.005 1858.108 150.90 161.25
Rust TrevRPC Unary 1 3 30441.471 33816.575 33.0 245.399 363.636 7.91 8.34
Rust gRPC Unary 1 3 32571.391 34209.791 30.8 324.675 194.805 7.96 7.96
Rust TrevRPC Unary 4 3 31358.975 33882.111 128.4 124.611 171.073 8.00 8.72
Rust gRPC Unary 4 3 32964.607 63111.167 120.2 168.350 132.231 8.11 8.17
C TrevRPC Client stream 1 3 66125.823 95027.199 15.2 921.053 5657.895 21.69 23.23
C gRPC Client stream 1 3 66846.719 69992.447 15.8 1733.333 4556.962 28.17 31.34
C TrevRPC Client stream 4 3 66453.503 98566.143 60.0 627.063 4625.850 22.04 24.07
C gRPC Client stream 4 3 55246.847 97648.639 70.8 1531.915 2000.000 28.73 33.93
C++ TrevRPC Client stream 1 3 35651.583 63111.167 28.0 642.857 1142.857 24.55 25.13
C++ gRPC Client stream 1 3 66584.575 94109.695 14.8 3098.592 5070.423 32.01 31.92
C++ TrevRPC Client stream 4 3 35782.655 66191.359 110.4 628.366 951.526 24.91 25.87
C++ gRPC Client stream 4 3 57540.607 101056.511 69.2 2640.845 3063.584 33.39 33.38
Go TrevRPC Client stream 1 3 47513.599 76808.191 19.0 3368.421 3837.209 21.16 21.58
Go gRPC Client stream 1 3 35913.727 68550.655 27.2 802.920 1102.941 20.91 20.70
Go TrevRPC Client stream 4 3 68550.655 132644.863 55.2 2210.145 3321.429 21.76 22.05
Go gRPC Client stream 4 3 40304.639 76808.191 93.2 547.550 835.735 21.09 21.02
JavaScript TrevRPC Client stream 1 3 41680.895 43450.367 24.0 3193.277 2666.667 84.68 81.64
JavaScript gRPC Client stream 1 3 68812.799 71172.095 14.8 5138.889 4305.556 95.20 84.42
JavaScript TrevRPC Client stream 4 3 41615.359 73924.607 90.0 2610.619 1777.778 94.79 82.77
JavaScript gRPC Client stream 4 3 128712.703 163839.999 30.6 2953.020 2684.564 102.01 92.07
Kotlin TrevRPC Client stream 1 3 67239.935 100794.367 15.0 10533.333 27733.333 133.78 179.23
Kotlin gRPC Client stream 1 3 38666.239 46399.487 25.4 8818.898 12538.462 158.89 168.98
Kotlin TrevRPC Client stream 4 3 37486.591 73662.463 97.4 5215.606 8431.772 161.87 159.55
Kotlin gRPC Client stream 4 3 39780.351 72613.887 96.4 3565.574 6925.466 174.91 193.70
Rust TrevRPC Client stream 1 3 51314.687 55312.383 20.4 784.314 784.314 8.20 8.60
Rust gRPC Client stream 1 3 35782.655 66453.503 25.4 393.701 338.983 8.20 8.00
Rust TrevRPC Client stream 4 3 36962.303 50659.327 106.4 468.384 563.910 8.79 8.90
Rust gRPC Client stream 4 3 43384.831 77725.695 87.0 229.885 321.839 8.26 8.64
C TrevRPC Server stream 1 3 66387.967 70647.807 15.2 666.667 5733.333 21.87 24.67
C gRPC Server stream 1 3 66977.791 69599.231 15.4 4285.714 1600.000 28.88 31.19
C TrevRPC Server stream 4 3 66387.967 97910.783 60.2 529.801 4668.874 22.18 25.84
C gRPC Server stream 4 3 51773.439 100532.223 73.2 1705.882 1205.882 29.86 32.36
C++ TrevRPC Server stream 1 3 35389.439 62259.199 28.0 729.927 921.986 24.80 25.68
C++ gRPC Server stream 1 3 66912.255 77332.479 15.0 5333.333 2800.000 32.00 31.91
C++ TrevRPC Server stream 4 3 35651.583 67043.327 111.4 493.506 789.946 25.04 25.78
C++ gRPC Server stream 4 3 64684.031 111017.983 59.2 3006.757 2321.900 33.43 32.21
Go TrevRPC Server stream 1 3 47906.815 82313.215 18.6 3010.753 3333.333 21.39 21.32
Go gRPC Server stream 1 3 36044.799 68157.439 24.8 1048.387 725.806 20.91 20.84
Go TrevRPC Server stream 4 3 65011.711 115605.503 59.6 2449.664 2283.237 21.66 21.77
Go gRPC Server stream 4 3 36503.551 70778.879 100.0 680.000 440.000 20.88 21.22
JavaScript TrevRPC Server stream 1 3 35323.903 42336.255 27.0 2910.448 2148.148 83.95 83.63
JavaScript gRPC Server stream 1 3 67764.223 101580.799 14.6 5405.405 4459.459 93.08 86.41
JavaScript TrevRPC Server stream 4 3 43909.119 67764.223 84.4 2500.000 1383.495 85.49 84.17
JavaScript gRPC Server stream 4 3 133431.295 165150.719 29.6 3484.848 2297.297 93.86 88.51
Kotlin TrevRPC Server stream 1 3 37748.735 69599.231 20.4 20196.078 8333.333 182.68 148.64
Kotlin gRPC Server stream 1 3 38731.775 49086.463 25.6 13464.567 8031.496 180.57 159.03
Kotlin TrevRPC Server stream 4 3 37421.055 72613.887 99.4 5835.010 5769.231 160.21 201.12
Kotlin gRPC Server stream 4 3 40566.783 87031.807 89.2 6860.987 3318.386 192.36 178.32
Rust TrevRPC Server stream 1 3 49348.607 63897.599 20.2 636.364 891.089 7.97 8.53
Rust gRPC Server stream 1 3 35979.263 67502.079 26.2 507.246 534.351 8.10 8.09
Rust TrevRPC Server stream 4 3 35782.655 47906.815 110.8 349.265 620.567 8.13 9.28
Rust gRPC Server stream 4 3 37748.735 69468.159 96.8 392.562 406.504 8.45 8.37
C TrevRPC Bidi 1 3 68943.871 100532.223 14.0 2428.571 7000.000 21.85 24.98
C gRPC Bidi 1 3 69730.303 112197.631 12.8 5714.286 4843.750 28.73 31.43
C TrevRPC Bidi 4 3 69337.087 103809.023 56.6 2120.141 6007.067 22.95 27.25
C gRPC Bidi 4 3 72744.959 137625.599 53.4 3595.506 3690.476 30.09 33.84
C++ TrevRPC Bidi 1 3 36896.767 70778.879 25.4 2240.000 2442.748 24.89 26.36
C++ gRPC Bidi 1 3 69206.015 102891.519 13.6 7714.286 7857.143 32.09 32.48
C++ TrevRPC Bidi 4 3 37027.839 72089.599 101.2 1976.517 2055.336 25.95 27.89
C++ gRPC Bidi 4 3 76546.047 115081.215 51.6 5420.168 5798.319 34.20 33.57
Go TrevRPC Bidi 1 3 50790.399 100270.079 17.6 5842.697 6625.000 21.30 21.80
Go gRPC Bidi 1 3 37421.055 68681.727 25.2 1587.302 1507.937 21.02 21.16
Go TrevRPC Bidi 4 3 80609.279 134086.655 49.2 4303.797 5147.679 22.04 22.23
Go gRPC Bidi 4 3 51904.511 85983.231 74.0 1172.070 1054.054 21.28 21.16
JavaScript TrevRPC Bidi 1 3 41549.823 79560.703 22.0 7321.429 12090.909 85.77 84.55
JavaScript gRPC Bidi 1 3 70123.519 103284.735 13.4 8955.224 7575.758 95.00 87.27
JavaScript TrevRPC Bidi 4 3 50266.111 98303.999 72.8 6027.397 6904.110 95.07 87.49
JavaScript gRPC Bidi 4 3 138936.319 206045.183 28.4 5673.759 4751.773 102.42 95.52
Kotlin TrevRPC Bidi 1 3 73400.319 133562.367 13.0 44909.091 48769.231 165.19 176.83
Kotlin gRPC Bidi 1 3 69730.303 103153.663 14.4 38133.333 22916.667 185.38 183.87
Kotlin TrevRPC Bidi 4 3 69468.159 119799.807 57.0 15501.730 19031.142 172.80 180.41
Kotlin gRPC Bidi 4 3 72613.887 120586.239 54.2 15166.052 10848.708 194.69 190.95
Rust TrevRPC Bidi 1 3 50855.935 67371.007 20.0 1276.596 1300.000 8.18 8.71
Rust gRPC Bidi 1 3 36831.231 68288.511 26.8 820.896 895.522 8.12 8.27
Rust TrevRPC Bidi 4 3 39911.423 77856.767 91.2 789.474 971.867 8.95 9.50
Rust gRPC Bidi 4 3 62980.095 106299.391 63.4 714.286 590.062 8.32 8.63

Campaign Context

Item Value
Measurement window 2026-07-16T02:46:34Z to 2026-07-16T03:19:53Z
Host ssh bench; AMD Ryzen 9 5900X; Linux 6.17.13-3-pve; x86-64
Effective CPUs 4 online CPUs (0-2,12); concurrency 4 matches the available CPU count
VM preflight 82-88% idle CPU with no competing user workload; approximately 1% steal time and elevated load averages remained sources of noise
Suite /nix/store/jhmbdxa4s638m3mal6fdvmmcc9b1jxib-trevrpc-bench-suite
Source Dirty source 5735bd77cd43ab2d694f4dbc13e26afcc33f414a-dirty
Matrix One interleaved campaign; 6 languages; 2 stacks; 4 RPC shapes; concurrencies 1 and 4; 3 repetitions; 288 final samples
Timing 1-second untimed warmup; 5-second fixed admission window; admitted operations drain to completion
Workload 256-byte request and response payloads; 128 messages per streaming RPC; zero-filled payloads with response sequence, length, and content validation
Network Separate client/server netns; 15 ms delay and 2 ms jitter each way; 0.1% random loss each way; 100 Mbit/s; 1,000-packet queues; MTU 1500
Transport TrevRPC native QUIC versus gRPC HTTP/2 over TCP on the same emulated path
Security TLS on both stacks; generated private CA; client trust configured explicitly; server identity verified
Metrics Direct client/server peer processes sampled from procfs every 10 ms

The effective qdiscs recorded in the manifest were:

client: qdisc netem 800b: root refcnt 25 limit 1000 delay 15ms 2ms loss 0.1% rate 100Mbit seed 3490255931690535313
server: qdisc netem 800c: root refcnt 25 limit 1000 delay 15ms 2ms loss 0.1% rate 100Mbit seed 18357758554390436507

Latency is complete bounded-RPC latency under closed-loop load. Throughput is derived from completions admitted during the fixed window. Client and server CPU are process CPU deltas divided by completed operations. Peak RSS is the highest sampled resident set during external monitoring.

gRPC Implementations

Language Implementation
C Low-level gRPC Core 1.80.0
C++ gRPC C++ 1.80.0
Go grpc-go 1.73.0
JavaScript @grpc/grpc-js 1.14.4
Kotlin grpc-java 1.82.2 with grpc-kotlin 1.5.0
Rust Tonic 0.14.6

The C comparison uses gRPC Core's low-level call and completion-queue API because gRPC does not provide a generated idiomatic C API. It measures the same service workload, but its API level differs from the generated C++, Go, JavaScript, Kotlin, and Rust implementations.

Artifact Provenance

aggregate.csv, samples.jsonl, and manifest.json in regional-wan-netns-20260715 are the canonical sources. The complete output is retained locally and is not currently downloadable from this wiki. Raw peer logs are retained as supporting diagnostics but are not authenticated by the hashes below. The campaign definition is published as regional-wan-netns.example.json; the tables below provide hashes for auditing a future copy of each listed artifact.

Artifact SHA-256
Campaign configuration e44e59e632628599b8abc83dc2fa32ee4e7fb2e28a558aef1291482aa997da74
manifest.json 991fd9feb1943f34ba884d5b123e40c258e3de9ef2c3fec9c85b919595042896
samples.jsonl 0a3f9ed8c9fefa91809cfe8405372ee0c873145a2ba2fb233eaa5b9a62ed1aff
aggregate.csv 1179764d06ee4b752defe6f6c72e3e43ba09fdba362648afe570c90acc36817c
Peer SHA-256
C 97095c8f2387cac9f12a15d3de10d8c5acb37a53da99c36caa7440a8f8604118
C++ 344c8b94f92895ce3169c245385f1658f141dd0b755fbe842aeff8cc3ff713e5
Go 51ec32d430667384552a42e2c5af67665b103c55bc1d545ad2337271b8c2bfa7
JavaScript aa5423b925ab1ccfb90dda450887693b81ccc2444dd6bb48633574464638cbe9
Kotlin f6c8b3c878c9955cf0dc5250ba1311372c327e6ab9ed6b52bae266c190227bd1
Rust 88676e45759c5946f00d60a51a6601785b17018c312e672936e5f34625765b21

All 288 samples completed with zero failed operations and no workload-configuration or request/response message-count mismatches. No sample was excluded.

The manifest and its hashes cover the campaign, source identifier, peer executable hashes, metrics scope, and effective netns configuration. They do not hash the benchmark controller or preserve the dirty source diff. The measurement window, host/kernel details, CPU allocation, and preflight observations came from the SSH orchestration log and are also not covered by the manifest hash.

Interpretation Boundaries

  • This is a reproducible synthetic regional-WAN profile on one host, not a geographically distributed network. It does not reproduce physical NIC offloads, routing changes, cross traffic, mobile handoffs, or cloud-provider behavior.
  • The selected 30 ms RTT, jitter, loss, bandwidth, queue, and MTU are representative parameters, not a universal definition of a real-world network. Other profiles may change the result materially.
  • Only three repetitions and 5-second admission windows were used. Using (maximum - minimum) / median, 44 of 96 throughput cells were below 5% spread and 61 were below 10%; the maximum was 56.55% for Rust gRPC client streaming at c4. Only 28 p99 cells were below 5% spread and 40 were below 10%; the maximum was 289.83% for C++ gRPC server streaming at c1.
  • Each reported p99 is the median of three per-run p99 bucket upper bounds, not a percentile pooled across all requests. The largest final histogram bucket upper bound was 414711.807 us for JavaScript gRPC server streaming at c4.
  • Closed-loop throughput and latency are coupled: slower operations reduce offered work. The results do not describe an open-loop arrival process, queue saturation, or overload shedding.
  • Streaming operations contain 128 messages while unary operations contain one request and one response. Cross-shape operations-per-second comparisons do not represent equal application work.
  • Streaming latency is complete bounded-RPC latency, not per-message latency.
  • CPU and peak RSS cover only direct peer processes. Runtime helpers inside those processes are included, but controller and namespace-holder processes are excluded.
  • The compared implementations differ above the common application contract, including language runtime, transport library, scheduler, memory management, buffering, and API level. The data cannot attribute a ratio solely to QUIC versus TCP or solely to TrevRPC versus gRPC.
  • The source revision was dirty. The local suite path and published hashes identify the retained artifacts and peer executables, but they do not make the controller's dirty source reproducible. A clean-source, longer campaign is required before release claims.