Skip to content

perf: box rare large variants of HandleResult / Command / Route - #2015

Merged
jkaczman merged 1 commit into
mainfrom
jk-shrink-moves
Nov 13, 2026
Merged

jkaczman merged 1 commit into
mainfrom
jk-shrink-moves

Conversation

@jkaczman

@jkaczman jkaczman commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor

HandleResult, Command and Route were previously pretty large because of a few rare variants and fields (size of a Rust enum is determined by the largest variant within)

Previously, HandleResult was 528 bytes, Command 512 and Route 376.

Rust copies the whole value whenever we either return it from a function, or pass it to one, which happens several times per request. E.g., the ? propagation in Server::send_one copies the HandleResult for every single message we send to Postgres.

Now, these variants and fields are Boxed, making HandleResult 184 bytes, Command 336 and Route 304.
And, of course, requests that don't use them don't need to allocate the boxes.

Now, 44% fewer bytes are copied per-request, and this removes ~1,200 instructions per request (-1.3%)

@jkaczman
jkaczman added this pull request to stack #2012 November 11, 2026 17:17
@codecov

codecov Bot commented Nov 11, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@github-actions

github-actions Bot commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor

Metal bench (arm64) failed. 15 of 517 measures outside bounds.

suite throughput cpu/txn user cycles/txn user instr/txn kernel cycles/txn kernel instr/txn ctx/txn
pooler 19.01 (-0.4% ± 0.5%) 18,429 (-1.6% ± 0.6%) 32,157 (-1.0% ± 0.04%) 30,151 (-0.1% ± 1.0%) 50,990 (-0.1% ± 0.3%)
lb 19.65 (-0.4% ± 1.2%) 19,039 (-1.7% ± 0.5%) 33,057 (-1.0% ± 0.05%) 31,085 (+0.6% ± 1.9%) 52,176 (+0.2% ± 0.7%)
sharding-w2 32.52 (-1.0% ± 1.3%) 44,475 (-1.3% ± 1.4%) 95,111 (-1.2% ± 0.01%) 40,210 (-0.7% ± 3.2%) 53,706 (+0.0% ± 0.1%) 1.545 (+0.1% ± 0.09%)
sharding-w8 237,758 (-0.9% ± 0.2%) 30.23 (+1.2% ± 0.3%) 45,845 (+0.9% ± 1.6%) 50,690 (-2.1% ± 0.02%) 37,724 (+1.7% ± 1.1%) 42,397 (-0.0% ± 0.07%) 0.1626 (-1.2% ± 2.8%)
Counters per txn
suite frontend stall l1i refill backend stall
pooler 7,680 (-3.7% ± 1.9%) 2,652 (-1.2% ± 1.0%)
lb 8,075 (-3.2% ± 1.2%) 2,714 (-1.3% ± 0.7%)
sharding-w2 18,813 (-2.6% ± 4.0%) 4,228 (-1.6% ± 2.1%)
sharding-w8 22,278 (+3.0% ± 3.8%) 4,367 (+1.9% ± 2.9%)
benchmark measure result baseline change bound
extended_cached::begin alloc_count 2 1 +100.00% ± 0.00% +0%
extended_cached::begin alloc_bytes 320 192 +66.67% ± 0.00% +1%
extended_cold::begin alloc_count 6 5 +20.00% ± 0.00% +0%
extended_cold::begin alloc_bytes 758 630 +20.32% ± 0.00% +1%
extended_evicting::begin alloc_count 5 4 +25.00% ± 0.00% +0%
extended_evicting::begin alloc_bytes 718 590 +21.69% ± 0.00% +1%
full_extended_cached::begin alloc_count 30 29 +3.45% ± 0.00% +0%
full_extended_cached::begin alloc_bytes 1,310 1,182 +10.83% ± 0.00% +1%
full_named_cached::begin alloc_count 25 24 +4.17% ± 0.00% +0%
full_named_cached::begin alloc_bytes 1,217 1,089 +11.75% ± 0.00% +1%
full_named_cached::insert instructions 61,607 60,924 +1.12% ± 0.00% +1%
full_simple::begin alloc_count 16 15 +6.67% ± 0.00% +0%
full_simple::begin alloc_bytes 1,423 1,295 +9.88% ± 0.00% +1%
simple_cold::begin alloc_count 5 4 +25.00% ± 0.00% +0%
simple_cold::begin alloc_bytes 718 590 +21.69% ± 0.00% +1%

Microbench: 489 of 504 measures within bounds.

  • extended_cached: 24 of 24 benches faster, median -3.0% ± 0.0%
  • extended_cold: 24 of 24 benches faster, median -1.1% ± 0.0%
  • extended_evicting: 23 of 24 benches faster, median -1.2% ± 0.0%
  • full_extended_cached: 24 of 24 benches faster, median -1.5% ± 0.0%
  • full_named_cached: 23 of 24 benches faster, median -1.6% ± 0.0%
  • full_simple: 24 of 24 benches faster, median -1.0% ± 0.0%
  • simple_cold: 24 of 24 benches faster, median -1.2% ± 0.0%
Microbench latency: 30 benches changed more than 3%
benchmark latency baseline change instructions change
extended_cached::order_limit_offset 2,068 ns 2,218 ns -6.73% ± 0.65% -2.75% ± 0.00%
extended_cached::having 2,284 ns 2,441 ns -6.44% ± 0.50% -2.41% ± 0.00%
extended_cached::delete_all_shards 1,380 ns 1,469 ns -6.06% ± 0.52% -4.66% ± 0.00%
extended_cached::begin 1,112 ns 1,177 ns -5.57% ± 0.53% -5.22% ± 0.00%
extended_cached::select_all_shards 1,816 ns 1,919 ns -5.36% ± 0.52% -3.46% ± 0.00%
extended_cached::delete_by_key 1,676 ns 1,763 ns -4.93% ± 0.19% -3.53% ± 0.00%
extended_cached::update_all_shards 1,511 ns 1,589 ns -4.91% ± 0.40% -4.04% ± 0.00%
extended_cached::select_in_list 2,495 ns 2,621 ns -4.81% ± 0.09% -2.16% ± 0.00%
extended_cached::insert 1,704 ns 1,786 ns -4.60% ± 0.36% -3.42% ± 0.00%
extended_cached::update_by_key 1,795 ns 1,876 ns -4.28% ± 0.38% -3.17% ± 0.00%
extended_cached::distinct 1,849 ns 1,930 ns -4.20% ± 0.22% -3.33% ± 0.00%
extended_cached::select_by_key 2,129 ns 2,219 ns -4.06% ± 0.41% -2.78% ± 0.00%
extended_cached::set 1,199 ns 1,249 ns -4.00% ± 0.18% -4.39% ± 0.00%
extended_cached::insert_returning 1,820 ns 1,892 ns -3.81% ± 0.75% -3.19% ± 0.00%
extended_cached::join 2,864 ns 2,976 ns -3.75% ± 0.31% -1.79% ± 0.00%
extended_cold::delete_all_shards 2,287 ns 2,375 ns -3.71% ± 0.20% -2.66% ± 0.00%
extended_cached::insert_split 5,140 ns 5,338 ns -3.71% ± 0.29% -2.95% ± 0.00%
full_extended_cached::delete_all_shards 15,882 ns 16,488 ns -3.67% ± 0.83% -3.09% ± 0.00%
extended_cold::begin 1,677 ns 1,740 ns -3.59% ± 0.42% -3.16% ± 0.00%
simple_cold::select_in_list 4,125 ns 4,275 ns -3.51% ± 0.68% -0.75% ± 0.00%
simple_cold::update_by_key 3,095 ns 3,205 ns -3.45% ± 0.86% -1.62% ± 0.00%
extended_cached::aggregate 2,166 ns 2,240 ns -3.29% ± 0.35% -2.97% ± 0.00%
extended_cached::lookup 2,363 ns 2,443 ns -3.26% ± 0.71% -2.53% ± 0.00%
extended_cached::group_by 2,159 ns 2,232 ns -3.25% ± 0.32% -2.65% ± 0.00%
full_extended_cached::insert_split 14,620 ns 15,108 ns -3.23% ± 0.63% -2.21% ± 0.00%
extended_evicting::begin 1,825 ns 1,885 ns -3.19% ± 0.64% -2.96% ± 0.00%
extended_cached::having_distinct_limit 2,606 ns 2,689 ns -3.09% ± 0.70% -1.96% ± 0.00%
simple_cold::update_all_shards 2,555 ns 2,637 ns -3.08% ± 0.90% -2.12% ± 0.00%
simple_cold::delete_all_shards 2,163 ns 2,231 ns -3.03% ± 1.78% -2.80% ± 0.00%
extended_cached::subquery 2,249 ns 2,319 ns -3.01% ± 0.57% -2.45% ± 0.00%
Hot code per txn
path base head change
pooler 116.1 KB 115.2 KB -0.9 KB
sharding-w2 167.4 KB 167.3 KB -0.1 KB

pooler:

crate base head change
pgdog::frontend::client::query_engine 19.8 KB 19.7 KB -0.1 KB
tokio 18.4 KB 18.2 KB -0.2 KB
pgdog::backend::pool 17.7 KB 17.5 KB -0.2 KB
aws-lc (TLS crypto) 10.4 KB 10.4 KB -0.1 KB
rustls (TLS) 8.3 KB 8.4 KB +0.1 KB
pgdog::frontend (other) 8.0 KB 7.9 KB -0.1 KB
pgdog::backend::server 7.4 KB 7.4 KB +0.0 KB
other 6.7 KB 6.9 KB +0.2 KB
everything else 19.4 KB 18.9 KB -0.4 KB
function head change
pgdog::frontend::client::Client::run::{{closure}} 5.6 KB -0.2 KB
pgdog::frontend::client::query_engine::query::<impl pgdog::frontend::client::query_engine: 5.2 KB -0.1 KB
pgdog::frontend::client::query_engine::QueryEngine::handle::{{closure}} 4.3 KB +0.1 KB
tokio::runtime::task::raw::poll 3.2 KB +0.1 KB
pgdog::backend::server::Server::read::{{closure}} 2.9 KB +0.1 KB

sharding-w2:

crate base head change
pgdog::frontend::router 29.2 KB 29.2 KB +0.0 KB
pgdog::frontend::client::query_engine 20.5 KB 21.1 KB +0.6 KB
tokio 18.4 KB 18.6 KB +0.2 KB
pgdog::backend::pool 18.1 KB 18.2 KB +0.1 KB
aws-lc (TLS crypto) 13.3 KB 12.5 KB -0.8 KB
other 10.1 KB 10.1 KB -0.1 KB
pgdog::frontend (other) 8.7 KB 8.5 KB -0.2 KB
rustls (TLS) 8.2 KB 8.2 KB -0.1 KB
everything else 40.9 KB 41.0 KB +0.1 KB
function head change
pgdog::frontend::client::Client::run::{{closure}} 6.1 KB -0.1 KB
pgdog::frontend::client::query_engine::query::<impl pgdog::frontend::client::query_engine: 5.1 KB +0.1 KB
pgdog::frontend::client::query_engine::QueryEngine::handle::{{closure}} 4.3 KB +0.2 KB
tokio::runtime::task::raw::poll 3.3 KB +0.2 KB
pgdog::frontend::router::parser::query::select::<impl pgdog::frontend::router::parser::que 3.3 KB -0.1 KB
lb flamegraph vs d04151f

lb

Open interactive for hover, zoom and search.

lb removed

Open interactive.

microbench flamegraph vs d04151f

microbench

Open interactive for hover, zoom and search.

microbench removed

Open interactive.

pooler flamegraph vs d04151f

pooler

Open interactive for hover, zoom and search.

pooler removed

Open interactive.

sharding-w2 flamegraph vs d04151f

sharding-w2

Open interactive for hover, zoom and search.

sharding-w2 removed

Open interactive.

sharding-w8 flamegraph vs d04151f

sharding-w8

Open interactive for hover, zoom and search.

sharding-w8 removed

Open interactive.

Logs

lb, microbench, pooler, sharding-w2, sharding-w8, verdict.json

Compared b2fe858 with d04151f on m8g.metal-24xl (on-demand).

@github-actions

github-actions Bot commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor

Metal bench (x86) failed. 16 of 517 measures outside bounds.

suite throughput cpu/txn user cycles/txn user instr/txn kernel cycles/txn kernel instr/txn ctx/txn
pooler 35.21 (-0.3% ± 0.2%) 23,751 (-0.8% ± 0.5%) 33,534 (-0.3% ± 0.02%) 58,432 (+0.0% ± 0.4%) 38,414 (+0.1% ± 0.1%)
lb 36.19 (-0.3% ± 0.5%) 25,002 (-0.7% ± 1.2%) 34,502 (-0.3% ± 0.03%) 59,177 (-0.1% ± 0.5%) 39,098 (+0.0% ± 0.2%)
sharding-w2 57.24 (-0.2% ± 0.7%) 54,268 (-0.4% ± 1.9%) 98,879 (-0.4% ± 0.01%) 73,824 (+0.0% ± 0.3%) 43,056 (+0.0% ± 0.5%) 1.387 (-0.0% ± 0.2%)
sharding-w8 146,204 (-0.8% ± 2.2%) 48.62 (-0.2% ± 0.8%) 58,938 (+0.0% ± 1.4%) 54,340 (-0.7% ± 0.1%) 64,552 (-0.4% ± 1.0%) 34,180 (-0.0% ± 0.1%) 0.1638 (-0.8% ± 2.4%)
Counters per txn
suite frontend stall l1i refill backend stall
pooler 77,284 (-0.5% ± 0.7%) 3,778 (+0.6% ± 0.1%)
lb 81,124 (-0.6% ± 1.5%) 3,933 (+0.7% ± 0.3%)
sharding-w2 168,214 (+1.3% ± 3.0%) 6,445 (+1.2% ± 0.2%)
sharding-w8 130,260 (+1.4% ± 1.9%) 5,091 (+1.3% ± 0.6%)
benchmark measure result baseline change bound
extended_cached::begin alloc_count 2 1 +100.00% ± 0.00% +0%
extended_cached::begin alloc_bytes 320 192 +66.67% ± 0.00% +1%
extended_cold::begin alloc_count 6 5 +20.00% ± 0.00% +0%
extended_cold::begin alloc_bytes 758 630 +20.32% ± 0.00% +1%
extended_cold::set instructions 14,345 13,943 +2.88% ± 0.00% +1%
extended_evicting::begin alloc_count 5 4 +25.00% ± 0.00% +0%
extended_evicting::begin alloc_bytes 718 590 +21.69% ± 0.00% +1%
full_extended_cached::begin alloc_count 30 29 +3.45% ± 0.00% +0%
full_extended_cached::begin alloc_bytes 1,310 1,182 +10.83% ± 0.00% +1%
full_named_cached::begin alloc_count 25 24 +4.17% ± 0.00% +0%
full_named_cached::begin alloc_bytes 1,217 1,089 +11.75% ± 0.00% +1%
full_named_cached::update_by_key instructions 65,239 64,207 +1.61% ± 0.00% +1%
full_simple::begin alloc_count 16 15 +6.67% ± 0.00% +0%
full_simple::begin alloc_bytes 1,423 1,295 +9.88% ± 0.00% +1%
simple_cold::begin alloc_count 5 4 +25.00% ± 0.00% +0%
simple_cold::begin alloc_bytes 718 590 +21.69% ± 0.00% +1%

Microbench: 488 of 504 measures within bounds.

Microbench latency: 11 benches changed more than 3%
benchmark latency baseline change instructions change
extended_cached::begin 1,296 ns 1,377 ns -5.88% ± 1.52% +0.02% ± 0.00%
extended_cached::select_all_shards 2,284 ns 2,390 ns -4.43% ± 1.29% -0.73% ± 0.00%
extended_cached::select_omni 1,996 ns 2,084 ns -4.22% ± 1.51% -0.90% ± 0.00%
extended_cached::group_by 2,754 ns 2,864 ns -3.84% ± 0.52% -0.55% ± 0.00%
extended_cached::update_all_shards 1,898 ns 1,972 ns -3.75% ± 1.36% -0.74% ± 0.00%
extended_cached::set 1,413 ns 1,467 ns -3.68% ± 0.95% -0.59% ± 0.00%
extended_cached::delete_all_shards 1,716 ns 1,773 ns -3.22% ± 0.92% -0.85% ± 0.00%
full_extended_cached::select_all_shards 28,610 ns 29,554 ns -3.19% ± 1.19% -0.79% ± 0.00%
extended_cached::select_by_key 2,705 ns 2,793 ns -3.15% ± 1.13% -0.58% ± 0.00%
extended_cached::delete_by_key 2,168 ns 2,238 ns -3.12% ± 1.15% -0.62% ± 0.00%
full_named_cached::subquery 27,974 ns 28,858 ns -3.06% ± 1.29% -1.16% ± 0.00%
Hot code per txn
path base head change
pooler 112.0 KB 110.4 KB -1.6 KB
sharding-w2 165.1 KB 166.8 KB +1.8 KB

pooler:

crate base head change
pgdog::frontend::client::query_engine 19.9 KB 20.8 KB +0.9 KB
tokio 17.8 KB 17.7 KB -0.1 KB
pgdog::backend::pool 17.2 KB 16.9 KB -0.2 KB
pgdog::frontend (other) 9.0 KB 8.6 KB -0.4 KB
aws-lc (TLS crypto) 7.2 KB 7.8 KB +0.5 KB
pgdog::backend::server 6.2 KB 6.9 KB +0.7 KB
rustls (TLS) 7.1 KB 6.9 KB -0.2 KB
other 6.8 KB 6.6 KB -0.2 KB
everything else 20.8 KB 18.2 KB -2.5 KB
function head change
pgdog::frontend::client::Client::run::{{closure}} 6.7 KB -0.4 KB
pgdog::frontend::client::query_engine::query::<impl pgdog::frontend::client::query_engine: 6.0 KB +0.4 KB
pgdog::frontend::client::query_engine::QueryEngine::handle::{{closure}} 4.7 KB +0.2 KB
tokio::runtime::task::raw::poll 3.6 KB +0.0 KB
pgdog::frontend::client::query_engine::query::<impl pgdog::frontend::client::query_engine: 3.0 KB -0.1 KB

sharding-w2:

crate base head change
pgdog::frontend::router 26.6 KB 27.2 KB +0.6 KB
pgdog::frontend::client::query_engine 22.4 KB 22.2 KB -0.2 KB
tokio 18.1 KB 18.4 KB +0.2 KB
pgdog::backend::pool 18.1 KB 18.3 KB +0.2 KB
other 10.8 KB 11.0 KB +0.2 KB
aws-lc (TLS crypto) 10.5 KB 10.6 KB +0.1 KB
jemalloc 10.3 KB 9.9 KB -0.4 KB
pgdog::frontend (other) 9.9 KB 9.8 KB -0.1 KB
everything else 38.2 KB 39.4 KB +1.2 KB
function head change
pgdog::frontend::client::Client::run::{{closure}} 7.5 KB +0.0 KB
pgdog::frontend::client::query_engine::query::<impl pgdog::frontend::client::query_engine: 5.9 KB +0.1 KB
pgdog::frontend::client::query_engine::QueryEngine::handle::{{closure}} 4.7 KB -0.3 KB
pgdog::frontend::router::parser::query::select::<impl pgdog::frontend::router::parser::que 4.2 KB +0.3 KB
tokio::runtime::task::raw::poll 3.8 KB -0.1 KB
lb flamegraph vs f74a176

lb

Open interactive for hover, zoom and search.

lb removed

Open interactive.

microbench flamegraph vs f74a176

microbench

Open interactive for hover, zoom and search.

microbench removed

Open interactive.

pooler flamegraph vs f74a176

pooler

Open interactive for hover, zoom and search.

pooler removed

Open interactive.

sharding-w2 flamegraph vs f74a176

sharding-w2

Open interactive for hover, zoom and search.

sharding-w2 removed

Open interactive.

sharding-w8 flamegraph vs f74a176

sharding-w8

Open interactive for hover, zoom and search.

sharding-w8 removed

Open interactive.

Logs

lb, microbench, pooler, sharding-w2, sharding-w8, verdict.json

Compared 87be3bd with f74a176 on c7a.metal-48xl (spot).

@jkaczman
jkaczman force-pushed the jk-shrink-moves branch 2 times, most recently from e6e539e to 0888656 Compare November 11, 2026 20:54
@jkaczman
jkaczman removed this pull request from stack #2012 November 13, 2026 18:11
@jkaczman
jkaczman added this pull request to stack #2032 November 13, 2026 18:13
@jkaczman
jkaczman force-pushed the jk-shrink-moves branch 4 times, most recently from afae259 to 87be3bd Compare November 13, 2026 18:46
Base automatically changed from jk-known-parameters to main November 13, 2026 18:54
@jkaczman
jkaczman merged commit a4b1f3b into main Nov 13, 2026
13 checks passed
@jkaczman
jkaczman deleted the jk-shrink-moves branch November 13, 2026 18:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant