crypto: optimize SipHash Write() method with chunked processing

Replace byte-by-byte processing in CSipHasher::Write() with an optimized
chunked approach that processes data in 8-byte aligned blocks when possible.

The previous implementation processed input data one byte at a time using
data.front() and data.subspan(1), which resulted in significant overhead
for large inputs due to repeated bounds checking and span manipulations.

The new implementation:
- Handles initial unaligned bytes to reach an 8-byte boundary
- Processes aligned 8-byte chunks directly using memcpy for efficiency
- Handles remaining bytes at the end

This optimization provides substantial performance improvements across
Bitcoin operations that rely on SipHash:
- GCSFilterConstruct: 16% improvement
- WalletIsMineDescriptors: 11.6% improvement
- WalletIsMineMigratedDescriptors: 59.0% improvement

These improvements are particularly beneficial for wallet operations and block filter construction.

./bin/bench_bitcoin -filter="(WalletIsMineMigratedDescriptors|WalletIsMineDescriptors|GCSFilterConstruct|AddrManSelect)" -output-csv=bench_old.csv --min-time=60000

|               ns/op |                op/s |    err% |     total | benchmark
|--------------------:|--------------------:|--------:|----------:|:----------
|              214.55 |        4,660,983.40 |    0.2% |     65.89 | `AddrManSelect`
|       12,983,090.72 |               77.02 |    0.1% |     66.00 | `GCSFilterConstruct`
|              100.29 |        9,971,046.61 |    0.0% |     66.02 | `WalletIsMineDescriptors`
|              115.42 |        8,664,379.92 |    0.0% |     66.02 | `WalletIsMineMigratedDescriptors`

./bin/bench_bitcoin -filter="(WalletIsMineMigratedDescriptors|WalletIsMineDescriptors|GCSFilterConstruct|AddrManSelect)" -output-csv=bench_new.csv --min-time=60000

|               ns/op |                op/s |    err% |     total | benchmark
|--------------------:|--------------------:|--------:|----------:|:----------
|              210.60 |        4,748,271.82 |    0.1% |     65.93 | `AddrManSelect`
|       11,155,751.42 |               89.64 |    0.1% |     65.99 | `GCSFilterConstruct`
|               89.87 |       11,126,702.73 |    0.0% |     66.01 | `WalletIsMineDescriptors`
|               72.67 |       13,761,145.85 |    0.0% |     66.01 | `WalletIsMineMigratedDescriptors`
This commit is contained in:
Raimo33 2025-09-17 19:23:05 +02:00
parent 720045094b
commit 5ba5198c45
1 changed files with 20 additions and 8 deletions

View File

@ -74,17 +74,29 @@ CSipHasher& CSipHasher::Write(std::span<const unsigned char> data)
t = 0;
}
// Process aligned 8-byte chunks directly
while (size >= 8) {
uint64_t chunk;
std::memcpy(&chunk, ptr, 8);
if constexpr (std::endian::native == std::endian::big) {
chunk = internal_bswap_64(chunk);
}
v3 ^= chunk;
SIPROUND;
SIPROUND;
v0 ^= chunk;
ptr += 8;
size -= 8;
c += 8;
}
//Handle remaining unaligned bytes
while (size > 0) {
t |= uint64_t{*ptr} << (8 * (c & 7));
c++;
if ((c & 7) == 0) {
v3 ^= t;
SIPROUND;
SIPROUND;
v0 ^= t;
t = 0;
}
ptr++;
c++;
size--;
}