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.