RustCrypto / hashes

Collection of cryptographic hash functions written in pure Rust
1.76k stars 239 forks source link

sha2: add `read_volatile` workaround for round constants #547

Closed newpavlov closed 6 months ago

newpavlov commented 6 months ago

Prevents compiler from inlining round constants or spilling them to stack, which can slightly improve performance.

For example, on my x86-64 laptop:

// Before:
test sha512_10    ... bench:          23 ns/iter (+/- 0) = 434 MB/s
test sha512_100   ... bench:         208 ns/iter (+/- 1) = 480 MB/s
test sha512_1000  ... bench:       2,015 ns/iter (+/- 7) = 496 MB/s
test sha512_10000 ... bench:      20,047 ns/iter (+/- 862) = 498 MB/s

// After:
test sha512_10    ... bench:          22 ns/iter (+/- 0) = 454 MB/s
test sha512_100   ... bench:         201 ns/iter (+/- 0) = 497 MB/s
test sha512_1000  ... bench:       1,941 ns/iter (+/- 3) = 515 MB/s
test sha512_10000 ... bench:      19,298 ns/iter (+/- 64) = 518 MB/s

Closes #328

newpavlov commented 6 months ago

@piegamesde Can you check that this PR indeed helps with performance issues on RISC-V?

piegamesde commented 6 months ago

Hi, and thank you for the fix. However, I cannot test it as I have quite working on embedded systems over a year ago, and the setup was for a work project.

tarcieri commented 6 months ago

or spilling them to stack

Interesting. Wonder if we could use that approach in the aes crate as well?

newpavlov commented 6 months ago

Wonder if we could use that approach in the aes crate as well?

It will be a bit harder to do. If there is enough registers, we want keys to stay in them, while read_volatile would always read them. In the sha2 case we know for certain that there is not enough registers, even on register rich targets like RISC-V, so reading round constants on every block processing is fine.