diff options
author | Felix Lange <fjl@users.noreply.github.com> | 2018-06-04 15:32:32 +0800 |
---|---|---|
committer | Péter Szilágyi <peterke@gmail.com> | 2018-06-04 15:32:32 +0800 |
commit | 3f33a7c8ceeefd769a68bbcc2ed3e4ce74ddaef8 (patch) | |
tree | 4a597f8066be7dbf50f0d73763d29e55fa685d2c | |
parent | c8dcb9584e1ea77c9b967d2bec5d167c7df410f0 (diff) | |
download | dexon-3f33a7c8ceeefd769a68bbcc2ed3e4ce74ddaef8.tar.gz dexon-3f33a7c8ceeefd769a68bbcc2ed3e4ce74ddaef8.tar.zst dexon-3f33a7c8ceeefd769a68bbcc2ed3e4ce74ddaef8.zip |
consensus/ethash: reduce keccak hash allocations (#16857)
Use Read instead of Sum to avoid internal allocations and
copying the state.
name old time/op new time/op delta
CacheGeneration-8 764ms ± 1% 579ms ± 1% -24.22% (p=0.000 n=20+17)
SmallDatasetGeneration-8 75.2ms ±12% 60.6ms ±10% -19.37% (p=0.000 n=20+20)
HashimotoLight-8 1.58ms ±11% 1.55ms ± 8% ~ (p=0.322 n=20+19)
HashimotoFullSmall-8 4.90µs ± 1% 4.88µs ± 1% -0.31% (p=0.013 n=19+18)
-rw-r--r-- | consensus/ethash/algorithm.go | 23 |
1 files changed, 17 insertions, 6 deletions
diff --git a/consensus/ethash/algorithm.go b/consensus/ethash/algorithm.go index 905a7b1ea..fa1c2c824 100644 --- a/consensus/ethash/algorithm.go +++ b/consensus/ethash/algorithm.go @@ -94,14 +94,25 @@ func calcDatasetSize(epoch int) uint64 { // reused between hash runs instead of requiring new ones to be created. type hasher func(dest []byte, data []byte) -// makeHasher creates a repetitive hasher, allowing the same hash data structures -// to be reused between hash runs instead of requiring new ones to be created. -// The returned function is not thread safe! +// makeHasher creates a repetitive hasher, allowing the same hash data structures to +// be reused between hash runs instead of requiring new ones to be created. The returned +// function is not thread safe! func makeHasher(h hash.Hash) hasher { + // sha3.state supports Read to get the sum, use it to avoid the overhead of Sum. + // Read alters the state but we reset the hash before every operation. + type readerHash interface { + hash.Hash + Read([]byte) (int, error) + } + rh, ok := h.(readerHash) + if !ok { + panic("can't find Read method on hash") + } + outputLen := rh.Size() return func(dest []byte, data []byte) { - h.Write(data) - h.Sum(dest[:0]) - h.Reset() + rh.Reset() + rh.Write(data) + rh.Read(dest[:outputLen]) } } |