Sequential SHA-512 comparison
Measured 2026-09-10 UTC. This is an order-of-magnitude comparison using the same C harness on all three machines, linked dynamically to their installed OpenSSL libraries. It measures a single dependent hash chain, not bulk hashing or throughput across independent messages:
x = 64 zero bytes
repeat N times:
x = SHA512(x)
| Machine | Tight chain, million H/s | ns/hash | Init/Update/Final chain, million H/s |
|---|---|---|---|
| Graviton5 | 8.512 | 117.5 | 8.744 |
| Apple M4 laptop | 13.476 | 74.2 | 12.473 |
| Hetzner EPYC Genoa VM | 6.230 | 160.5 | 5.521 |
The tight-chain column averages two runs of 20 million hashes each. The API column is one run of 10 million hashes. All rates refer to complete 64-byte SHA-512 digests, with exactly one padded SHA-512 compression block per hash.
Graviton5 is about 1.37 times as fast as this Hetzner machine in the tight chain. The M4 is about 1.58 times as fast as Graviton5. All three operate around 10^7 hashes/s; there is no order-of-magnitude separation here. The API variant is slightly faster on Graviton and slower on the other two, illustrating that wrapper code and compiler output also affect such short operations.
What is timed
bench.c uses OpenSSL's public SHA512_Transform API with the standard initial
state and fixed padding for a 64-byte message, serializes the resulting digest,
and immediately uses it as the next message. Resetting the state, serialization,
and loop overhead are included. It avoids per-hash algorithm lookup, allocation,
and general streaming API bookkeeping, while calculating ordinary SHA-512.
The API control uses SHA512_Init, SHA512_Update, and SHA512_Final for every
hash. Both modes start from the same seed. The harness uses the public LP64
SHA512_CTX layout and resolves public functions from the installed libcrypto.
It does not modify OpenSSL or either deployed relay.
Every invocation checks the standard SHA-512("abc") vector and compares both implementations after 1,000 chained hashes. The runner independently checks that 1,000-step result with Python hashlib. Corresponding full-run final digests match across all three machines. The transferred C source digests also match.
SHA-512 instruction control
OpenSSL's ARM capability definitions assign bit 6 to ARMV8_SHA512. Each ARM control run cleared only that bit from the capabilities reported by its OpenSSL installation. Other detected features were preserved. The controls ran 2 million dependent hashes:
| Machine | SHA-512 instructions enabled | Disabled | Enabled/disabled |
|---|---|---|---|
| Graviton5 | 8.512 million H/s | 6.245 million H/s | 1.36x |
| Apple M4 | 13.476 million H/s | 7.430 million H/s | 1.81x |
The two disabled-instruction runs also produced matching final digests. This measures OpenSSL dispatch choices on these machines, not an isolated instruction latency or a guaranteed speedup for a modified RandomX workload.
Environment and limits
- Graviton5: c9g.4xlarge parent CPU 13, pinned with
taskset; native host OpenSSL 3.5.7. The existing ARM toolchain Docker image compiled the C harness; the executable ran directly on the host. The build container used no network and remains stopped. The production enclave was not restarted. - Hetzner: existing EPYC Genoa KVM guest, pinned to vCPU 1; OpenSSL 3.0.13. Exposed flags include SHA-NI, AVX2 and AVX-512, but not SHA-512 acceleration. SHA-NI alone accelerates SHA-1/SHA-256, not SHA-512. Physical host sharing is unknown.
- Laptop: Apple M4, native arm64, OpenSSL 3.6.3; one worker, macOS scheduler
controlled, not pinned. AC attached; charging. No thermal/performance warning
was reported by
pmset. Background applications were left running. - Different OpenSSL versions and compilers mean this is a practical comparison of available implementations, not a controlled microarchitecture comparison.
- Timed runs last approximately 1.5–3.2 seconds for the tight-chain measurements. These are short estimates, not multi-day sustained rates or hardware maxima.
- Results concern the measured machines. They do not establish a bound for newer x86 CPUs, other ARM CPUs, or specialized SHA-512 hardware.
run.py records exact commands, capability overrides, library versions, source
and binary digests, timing, and output digests. Raw stdout/stderr and parsed JSON
are in each machine's subdirectory. summary.json retains the derived values.