Skip to content

build: fat LTO, code alignment and jemalloc for the release binary - #50

Merged
CMGS merged 1 commit into
mainfrom
build/release-profile-jemalloc
Sep 3, 2026
Merged

build: fat LTO, code alignment and jemalloc for the release binary#50
CMGS merged 1 commit into
mainfrom
build/release-profile-jemalloc

Conversation

@CMGS

@CMGS CMGS commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

The release profile shipped cargo defaults. This sets lto = "fat" and codegen-units = 1, aligns functions to 64 bytes and branch targets to 32 bytes through .cargo/config.toml, and makes gw run on jemalloc as its global allocator. One sentence in docs/deployment.md; no other code change.

Why: on a Zen 5 host, 4e78c36 lost 6-7% single-lane throughput on 48 KB bodies against 5e94caa while executing the same instruction stream to 0.01% — op-cache misses per request tripled (68k → 158k) because the link layout moved serde_json's escaped-string loops onto worse fetch windows; the malloc/realloc sequence, data-side counters and page faults were identical. With the alignment flags both layouts sit at 43k op-cache misses per request and within 0-3% of each other, no lane below its default. Fat LTO + one codegen unit measured +13% on small bodies and -31% binary; jemalloc (LD_PRELOAD control) +16% on small bodies for either layout while leaving the big-body layout gap untouched.

Gates: cargo fmt --check, cargo clippy --workspace --all-targets -- -D warnings, cargo test --workspace, cargo deny check clean on macOS and in a rust:1.98.0 Linux container; release build 129 s on the mac (was ~45 s), Linux binary 23.5 MB (was 30.9 MB). The interleaved A/B against main (single-big, pg40-big, single-small; instr/req, op-cache misses) follows in a comment.

The release profile shipped cargo defaults. On a Zen 5 host the big-body
request path lost 6-7% throughput between two commits that execute the
same instruction stream: op-cache misses tripled because the link layout
moved serde_json's escaped-string loops onto worse fetch windows. Aligning
functions to 64 bytes and branch targets to 32 bytes puts both layouts at
the same op-cache miss rate. Fat LTO with one codegen unit is +13% on small
bodies and -30% binary size; jemalloc is +16% on small bodies for either
layout.
@CMGS

CMGS commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator Author

Interleaved A/B on the Zen 5 bench host, main 4e78c36 (cargo default profile, glibc malloc) vs this branch at 97391ae, both built in the same rust:1 container, three rotated reps per lane, load-gated, oha -c 256, mock transport (zero egress), PG + Redis for the pool lane:

lane main rps (median of 3) PR rps delta p50 ms main → PR p99 ms main → PR
single, 48 KB bodies 52,209 56,573 +8.4% 4.63 → 4.27 10.94 → 10.18
pg pool 40, 48 KB bodies 28,815 29,234 +1.5% 10.61 → 10.45 20.99 → 20.78
single, small bodies 303,583 394,054 +29.8% 0.76 → 0.52 1.86 → 1.82

Per request over 300k big-body requests on the single lane: instructions 4,044,274 → 4,056,743 (+0.3%, LTO inlining), cycles 1,486,446 → 1,332,407 (−10.4%), IPC 2.72 → 3.05, op-cache misses 155,198 → 77,210, front-end no-op slots 4.94M → 3.51M. All responses 200. Linux binary 30.9 MB → 24.9 MB.

@CMGS
CMGS merged commit 92a7bf7 into main Sep 3, 2026
2 checks passed
@CMGS
CMGS deleted the build/release-profile-jemalloc branch September 3, 2026 14:31
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