Skip to content

Commit c89a3da

Browse files
core/state/snapshot: use AddHash/ContainHash instead of Hasher interface (#28849)
This change switches from using the `Hasher` interface to add/query the bloomfilter to implementing it as methods. This significantly reduces the allocations for Search and Rebloom.
1 parent 4c8d92d commit c89a3da

File tree

2 files changed

+22
-56
lines changed

2 files changed

+22
-56
lines changed

core/state/pruner/bloom.go

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,10 @@ import (
2727
bloomfilter "github.com/holiman/bloomfilter/v2"
2828
)
2929

30-
// stateBloomHasher is a wrapper around a byte blob to satisfy the interface API
31-
// requirements of the bloom library used. It's used to convert a trie hash or
32-
// contract code hash into a 64 bit mini hash.
33-
type stateBloomHasher []byte
34-
35-
func (f stateBloomHasher) Write(p []byte) (n int, err error) { panic("not implemented") }
36-
func (f stateBloomHasher) Sum(b []byte) []byte { panic("not implemented") }
37-
func (f stateBloomHasher) Reset() { panic("not implemented") }
38-
func (f stateBloomHasher) BlockSize() int { panic("not implemented") }
39-
func (f stateBloomHasher) Size() int { return 8 }
40-
func (f stateBloomHasher) Sum64() uint64 { return binary.BigEndian.Uint64(f) }
30+
// stateBloomHash is used to convert a trie hash or contract code hash into a 64 bit mini hash.
31+
func stateBloomHash(f []byte) uint64 {
32+
return binary.BigEndian.Uint64(f)
33+
}
4134

4235
// stateBloom is a bloom filter used during the state conversion(snapshot->state).
4336
// The keys of all generated entries will be recorded here so that in the pruning
@@ -113,10 +106,10 @@ func (bloom *stateBloom) Put(key []byte, value []byte) error {
113106
if !isCode {
114107
return errors.New("invalid entry")
115108
}
116-
bloom.bloom.Add(stateBloomHasher(codeKey))
109+
bloom.bloom.AddHash(stateBloomHash(codeKey))
117110
return nil
118111
}
119-
bloom.bloom.Add(stateBloomHasher(key))
112+
bloom.bloom.AddHash(stateBloomHash(key))
120113
return nil
121114
}
122115

@@ -128,5 +121,5 @@ func (bloom *stateBloom) Delete(key []byte) error { panic("not supported") }
128121
// - If it says yes, the key may be contained
129122
// - If it says no, the key is definitely not contained.
130123
func (bloom *stateBloom) Contain(key []byte) bool {
131-
return bloom.bloom.Contains(stateBloomHasher(key))
124+
return bloom.bloom.ContainsHash(stateBloomHash(key))
132125
}

core/state/snapshot/difflayer.go

Lines changed: 15 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -124,47 +124,20 @@ type diffLayer struct {
124124
lock sync.RWMutex
125125
}
126126

127-
// destructBloomHasher is a wrapper around a common.Hash to satisfy the interface
128-
// API requirements of the bloom library used. It's used to convert a destruct
129-
// event into a 64 bit mini hash.
130-
type destructBloomHasher common.Hash
131-
132-
func (h destructBloomHasher) Write(p []byte) (n int, err error) { panic("not implemented") }
133-
func (h destructBloomHasher) Sum(b []byte) []byte { panic("not implemented") }
134-
func (h destructBloomHasher) Reset() { panic("not implemented") }
135-
func (h destructBloomHasher) BlockSize() int { panic("not implemented") }
136-
func (h destructBloomHasher) Size() int { return 8 }
137-
func (h destructBloomHasher) Sum64() uint64 {
127+
// destructBloomHash is used to convert a destruct event into a 64 bit mini hash.
128+
func destructBloomHash(h common.Hash) uint64 {
138129
return binary.BigEndian.Uint64(h[bloomDestructHasherOffset : bloomDestructHasherOffset+8])
139130
}
140131

141-
// accountBloomHasher is a wrapper around a common.Hash to satisfy the interface
142-
// API requirements of the bloom library used. It's used to convert an account
143-
// hash into a 64 bit mini hash.
144-
type accountBloomHasher common.Hash
145-
146-
func (h accountBloomHasher) Write(p []byte) (n int, err error) { panic("not implemented") }
147-
func (h accountBloomHasher) Sum(b []byte) []byte { panic("not implemented") }
148-
func (h accountBloomHasher) Reset() { panic("not implemented") }
149-
func (h accountBloomHasher) BlockSize() int { panic("not implemented") }
150-
func (h accountBloomHasher) Size() int { return 8 }
151-
func (h accountBloomHasher) Sum64() uint64 {
132+
// accountBloomHash is used to convert an account hash into a 64 bit mini hash.
133+
func accountBloomHash(h common.Hash) uint64 {
152134
return binary.BigEndian.Uint64(h[bloomAccountHasherOffset : bloomAccountHasherOffset+8])
153135
}
154136

155-
// storageBloomHasher is a wrapper around a [2]common.Hash to satisfy the interface
156-
// API requirements of the bloom library used. It's used to convert an account
157-
// hash into a 64 bit mini hash.
158-
type storageBloomHasher [2]common.Hash
159-
160-
func (h storageBloomHasher) Write(p []byte) (n int, err error) { panic("not implemented") }
161-
func (h storageBloomHasher) Sum(b []byte) []byte { panic("not implemented") }
162-
func (h storageBloomHasher) Reset() { panic("not implemented") }
163-
func (h storageBloomHasher) BlockSize() int { panic("not implemented") }
164-
func (h storageBloomHasher) Size() int { return 8 }
165-
func (h storageBloomHasher) Sum64() uint64 {
166-
return binary.BigEndian.Uint64(h[0][bloomStorageHasherOffset:bloomStorageHasherOffset+8]) ^
167-
binary.BigEndian.Uint64(h[1][bloomStorageHasherOffset:bloomStorageHasherOffset+8])
137+
// storageBloomHash is used to convert an account hash and a storage hash into a 64 bit mini hash.
138+
func storageBloomHash(h0, h1 common.Hash) uint64 {
139+
return binary.BigEndian.Uint64(h0[bloomStorageHasherOffset:bloomStorageHasherOffset+8]) ^
140+
binary.BigEndian.Uint64(h1[bloomStorageHasherOffset:bloomStorageHasherOffset+8])
168141
}
169142

170143
// newDiffLayer creates a new diff on top of an existing snapshot, whether that's a low
@@ -233,14 +206,14 @@ func (dl *diffLayer) rebloom(origin *diskLayer) {
233206
}
234207
// Iterate over all the accounts and storage slots and index them
235208
for hash := range dl.destructSet {
236-
dl.diffed.Add(destructBloomHasher(hash))
209+
dl.diffed.AddHash(destructBloomHash(hash))
237210
}
238211
for hash := range dl.accountData {
239-
dl.diffed.Add(accountBloomHasher(hash))
212+
dl.diffed.AddHash(accountBloomHash(hash))
240213
}
241214
for accountHash, slots := range dl.storageData {
242215
for storageHash := range slots {
243-
dl.diffed.Add(storageBloomHasher{accountHash, storageHash})
216+
dl.diffed.AddHash(storageBloomHash(accountHash, storageHash))
244217
}
245218
}
246219
// Calculate the current false positive rate and update the error rate meter.
@@ -301,9 +274,9 @@ func (dl *diffLayer) AccountRLP(hash common.Hash) ([]byte, error) {
301274
}
302275
// Check the bloom filter first whether there's even a point in reaching into
303276
// all the maps in all the layers below
304-
hit := dl.diffed.Contains(accountBloomHasher(hash))
277+
hit := dl.diffed.ContainsHash(accountBloomHash(hash))
305278
if !hit {
306-
hit = dl.diffed.Contains(destructBloomHasher(hash))
279+
hit = dl.diffed.ContainsHash(destructBloomHash(hash))
307280
}
308281
var origin *diskLayer
309282
if !hit {
@@ -372,9 +345,9 @@ func (dl *diffLayer) Storage(accountHash, storageHash common.Hash) ([]byte, erro
372345
dl.lock.RUnlock()
373346
return nil, ErrSnapshotStale
374347
}
375-
hit := dl.diffed.Contains(storageBloomHasher{accountHash, storageHash})
348+
hit := dl.diffed.ContainsHash(storageBloomHash(accountHash, storageHash))
376349
if !hit {
377-
hit = dl.diffed.Contains(destructBloomHasher(accountHash))
350+
hit = dl.diffed.ContainsHash(destructBloomHash(accountHash))
378351
}
379352
var origin *diskLayer
380353
if !hit {

0 commit comments

Comments
 (0)