Skip to content

perf: prepare Ed25519 verifying keys at import time - #139

Merged
AkshatM merged 1 commit into
cloudflare:mainfrom
benni-rogge:perf/prepare-verifying-keys
Aug 31, 2026
Merged

perf: prepare Ed25519 verifying keys at import time#139
AkshatM merged 1 commit into
cloudflare:mainfrom
benni-rogge:perf/prepare-verifying-keys

Conversation

@benni-rogge

@benni-rogge benni-rogge commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Summary

MessageVerifier::verify ran VerifyingKey::try_from on every Ed25519 request, repeating point decompression for keys that never change. Keys are now prepared once when a keyring entry is created (import_raw, FromIterator, JWK import, rename all covered) and borrowed during verification.

Internally the ring stores { raw, prepared } entries; raw keeps the public get API unchanged. prepared is Option<VerifyingKey>: None preserves the existing deferred InvalidKeyLength result for raw bytes that cannot form a valid key. No public API or error-behavior changes. We run this verifier in a high-throughput edge component, where the per-request savings accumulate.

Testing

  • cargo +stable test --workspace --all-features --all-targets: 38 pass, incl. new tests for invalid key material, invalid signature, unsupported algorithm, duplicate import, renamed key.
  • cargo +stable clippy --workspace --all-features --all-targets -- -D warnings: clean. cargo fmt --check: clean.
  • cargo +stable bench -p web-bot-auth --bench keyring_verify: runs both verify-only and end-to-end with 30,000 iterations and prints nanoseconds per iteration. No additional benchmark dependency is required.

A three-run local A/B using the committed cargo bench target produced these median results:

mode baseline optimized delta
verify-only 20,770 ns/iteration 18,613 ns/iteration -10.4%
end-to-end 21,741 ns/iteration 19,514 ns/iteration -10.2%

As an additional manual cross-check, I ran a locally installed Hyperfine binary against baseline and optimized executables built with identical flags (-C llvm-args=-align-all-functions=6). Hyperfine is not a project dependency and is not required to run the committed benchmark. Twenty runs in both command orderings produced:

mode baseline optimized delta
verify-only 1.277s / 1.255s 1.153s / 1.130s ~-10%
end-to-end 1.323s / 1.301s 1.186s / 1.179s ~-10%

Approximately 2.1 microseconds saved per verification; no end-to-end regression.

@AkshatM
AkshatM marked this pull request as ready for review August 31, 2026 14:10
@benni-rogge
benni-rogge force-pushed the perf/prepare-verifying-keys branch 2 times, most recently from e98f861 to c82991f Compare August 31, 2026 14:19
@AkshatM

AkshatM commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Thank you for this contribution, it's useful!

Two questions:

  • Why does the benchmark support Hyperfine exclusively and not cargo bench?
  • If Hyperfine is required, can the dependency for it be added to the relevant Github Actions, please?

I'm mostly just trying to figure out whether an external dependency is really needed and, if so, how it should be packaged so that we can run this bench automatically.

@benni-rogge

Copy link
Copy Markdown
Contributor Author

Thank you for this contribution, it's useful!

Two questions:

  • Why does the benchmark support Hyperfine exclusively and not cargo bench?
  • If Hyperfine is required, can the dependency for it be added to the relevant Github Actions, please?

I'm mostly just trying to figure out whether an external dependency is really needed and, if so, how it should be packaged so that we can run this bench automatically.

I really like to use hyperfine. Let me rerun it in cargo bench to check if we are seeing the same results. If so, let me remove the comment. You are right that this should not be a new mandatory test dependency

VerifyingKey::try_from was executed on every verification. Keys are
now prepared once when a keyring entry is created and borrowed during
verification. Invalid raw key material keeps the deferred
InvalidKeyLength behavior; public APIs are unchanged.

Adds a deterministic harness=false benchmark (keyring_verify) with
verify-only and end-to-end modes.

Assisted-By: devx/bcb08cbe-f194-4c2c-a5a0-0c3b36297da9
@benni-rogge
benni-rogge force-pushed the perf/prepare-verifying-keys branch from c82991f to ea6b807 Compare August 31, 2026 14:35
@benni-rogge

Copy link
Copy Markdown
Contributor Author

Thank you for this contribution, it's useful!

Two questions:

  • Why does the benchmark support Hyperfine exclusively and not cargo bench?
  • If Hyperfine is required, can the dependency for it be added to the relevant Github Actions, please?

I'm mostly just trying to figure out whether an external dependency is really needed and, if so, how it should be packaged so that we can run this bench automatically.

removed hyperfine and used cargo bench exclusively.

@AkshatM
AkshatM merged commit d8936b9 into cloudflare:main Aug 31, 2026
5 checks passed
@benni-rogge
benni-rogge deleted the perf/prepare-verifying-keys branch August 31, 2026 17:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants