Benchmarks
eth.zig vs alloy.rs -- head-to-head performance comparison across 26 Ethereum operations.
eth.zig vs Rust -- a head-to-head performance comparison of eth.zig and alloy.rs across 26 core Ethereum operations.
Score: eth.zig wins 23/26 | alloy.rs wins 1/26 | tied 2/26
Benchmarks run on Apple Silicon with ReleaseFast (Zig) vs --release (Cargo). Custom criterion-style harness with 0.5s warmup, calibrated batch sizes, and 2s measurement window. Both mulDiv benchmarks use true 512-bit intermediate arithmetic.
Full Results
| Benchmark | eth.zig | alloy.rs | Winner |
|---|---|---|---|
| keccak256_empty | 257 ns | 334 ns | zig 1.30x |
| keccak256_32b | 259 ns | 336 ns | zig 1.30x |
| keccak256_256b | 519 ns | 639 ns | zig 1.23x |
| keccak256_1kb | 2,000 ns | 2,494 ns | zig 1.25x |
| keccak256_4kb | 7,673 ns | 9,292 ns | zig 1.21x |
| secp256k1_sign | 24,609 ns | 51,738 ns | zig 2.10x |
| secp256k1_sign_recover | 54,221 ns | 218,790 ns | zig 4.04x |
| address_derivation | 262 ns | 363 ns | zig 1.39x |
| address_from_hex | 15 ns | 11 ns | rs 1.36x |
| checksum_address | 307 ns | 387 ns | zig 1.26x |
| abi_encode_transfer | 25 ns | 55 ns | zig 2.20x |
| abi_encode_static | 24 ns | 97 ns | zig 4.04x |
| abi_encode_dynamic | 171 ns | 324 ns | zig 1.89x |
| abi_decode_uint256 | 16 ns | 50 ns | zig 3.12x |
| abi_decode_dynamic | 32 ns | 256 ns | zig 8.00x |
| rlp_encode_eip1559_tx | 55 ns | 72 ns | zig 1.31x |
| rlp_decode_u256 | 8 ns | 9 ns | zig 1.12x |
| u256_add | 4 ns | 4 ns | tie |
| u256_mul | 4 ns | 10 ns | zig 2.50x |
| u256_div | 7 ns | 24 ns | zig 3.43x |
| u256_uniswapv2_amount_out | 21 ns | 24 ns | zig 1.14x |
| u256_mulDiv | 17 ns | 29 ns | zig 1.71x |
| u256_uniswapv4_swap | 41 ns | 45 ns | zig 1.10x |
| hex_encode_32b | 21 ns | 21 ns | tie |
| hex_decode_32b | 23 ns | 28 ns | zig 1.22x |
| tx_hash_eip1559 | 328 ns | 402 ns | zig 1.23x |
Score Summary
| Count | |
|---|---|
| eth.zig wins | 23 |
| alloy.rs wins | 1 |
| Tied | 2 |
Key Optimizations
| Optimization | Impact |
|---|---|
| bitcoin-core/secp256k1 C backend (vendored) | secp256k1_sign: 2.10x faster than alloy; sign_recover: 4.04x faster |
| Lane-complementing Keccak-f[1600] (XKCP opt64) | keccak256_4kb: 1.21x faster than alloy |
| Streamlined mulDiv with native u128 division | mulDiv: 1.71x faster than alloy (17ns vs 29ns) |
| mulWide + divWide (Knuth D for 512-bit) | Replaces 256-iteration binary long division with ~4-iteration Knuth D |
| U256Limb limb-native arithmetic | uniswapv2: beats alloy 1.14x |
Half-word division (div128by64) | u256_div: 7ns, 3.43x faster than alloy |
| FixedBufferAllocator in benchmarks | Eliminates allocator overhead for ABI/RLP/TX benchmarks |
| Vendored bitcoin-core/secp256k1 + XKCP keccak | Best-in-class C backends compiled by zig build |
| Custom criterion-style harness | Accurate timing in the sub-25ns regime; zbench had ~25ns floor on macOS |
Where alloy.rs Wins
| Benchmark | Gap | Root Cause |
|---|---|---|
| address_from_hex | 1.36x | alloy uses SIMD hex parsing; eth.zig uses scalar loop |
Reproducing
# Full comparison (requires Zig, Rust, Python 3)
bash bench/compare.sh
# eth.zig benchmarks only
zig build bench
# alloy benchmarks only
(cd bench/alloy-bench && cargo bench --bench eth_comparison)