Repository navigation
ChaCha20-Poly1305 on x86-64: fewer stores and calls for short messages - #1349
Merged
Merged
Conversation
Base automatically changed from
claude/chacha20poly1305-gather-wide-copy
to
main
October 8, 2026 17:14
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ma2fA9rUTPXEEQjYyCMCRw
alex
force-pushed
the
claude/chacha20poly1305-small-messages
branch
from
October 8, 2026 17:14
8131c45 to
8e12d6e
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
From the rustls provider analysis in #991. Below 1 KiB, that provider's ChaCha20-Poly1305 was 0.58–0.84× as fast as aws-lc-rs on a Cascade Lake–class Xeon. At 16 bytes it took 322 ns against aws-lc-rs's 197 ns. Above about 4 KiB it was faster than aws-lc-rs. Below 1 KiB the fixed cost of each call dominates. Much of that cost is stores, about 270 for a 16-byte seal, and Cascade Lake can do only one store per cycle. This PR cuts those stores and some calls. It changes neither the vector ChaCha20 nor Poly1305.
Change
All in
vg_chacha20_poly1305_seal/_open(Impl/ChaCha20Poly1305/X86_64.lean), for every variant:initStateQ). Before, they were written 4 bytes at a time. That is 8 stores instead of 16 per copy.pxor/movdquinstead of 8 at a time (zeroKs).xorBufX).wholeBlocks).macPadLengths).withStackArgScratchWipedX, new besidewithStackArgScratchWipedinImpl/StackScratch/X86_64.lean).Verified.stackArgScratchWipedBy, is generic over the wiping code (Wiper). The existingVerified.stackArgScratchWipedis now a corollary with the same statement, so its other callers are unchanged.No TCB or spec change, no new instructions (
pxor,movdqu,movImm64andshlare all in the baseline model), and no Rust change. Onlysrc/asm/x86_64/chacha20poly1305.rsis regenerated.Proof
CT.leanis reworked for the new code:stQ_ok,initStateQ_ok, and theqOf_*lemmas relating each quadword to the spec's words.wholeBlocks_ok,macTail_ok,macRest_ok,macPad_ok,macPadLengths_ok.seal/opencorrectness on top of these.XorBufX.lean: the 16-byte XOR loop and its frame.StackArgScratchWipe.lean:Wiper, the generalized wipe proof, andwipeAtX_run/wipeAtX_spSafe.taint_decide.CT.leanuses one fewerdecide := truesimp, soci/lean_speed_allowed.pygoes from 19 to 18.Measurements
These were taken on a Sapphire Rapids–class Xeon, this repo's development VM, with
ci/bench_compare.py --rounds 5. Each figure is the fastest of 5 interleaved runs, against #1345. The Cascade Lake machine where the gap was measured isn't available to me.chacha20poly1305(in-place seal) /-decrypt/-encrypt-out-of-place(two pieces):AVX-512 gains most between 256 and 768 bytes, where the message ends in a scalar tail and a partial block. That is exactly where one Poly1305 call is now skipped and another merged. The few small slowdowns are within run-to-run noise. Recent x86-64 CI benchmark runners have been AMD EPYC 7763 (no AVX-512), so the AVX-512 rows can't be checked there.
This is a step, not the whole gap. On this machine we already beat aws-lc-rs at these sizes (64 B: 202 vs 259 ns), so the Cascade Lake gap is specific to that CPU. One possible cause is its cost for 512-bit registers; aws-lc-rs's ChaCha20 doesn't use AVX-512. That needs a measurement there.
Checks
lake buildandEmit.lean, done on the revision the CI cache was built from. The Lean sources andsrc/asm/x86_64/chacha20poly1305.rsare byte-identical on this branch.check_lean_imports,check_lean_speed,check_variants,check_mcdt,check_arch_gates,check_vectors.VG_CPU_FEATURESunset (AVX-512), AVX2-only andnone.🤖 Generated with Claude Code
https://claude.ai/code/session_01Ma2fA9rUTPXEEQjYyCMCRw
Generated by Claude Code