@@ -189,7 +189,7 @@ func (l *lookup) addLayer(diff *diffLayer) {
189189 for accountHash := range diff .states .accountData {
190190 list , exists := l .accounts [accountHash ]
191191 if ! exists {
192- list = make ([]common. Hash , 0 , 16 ) // TODO(rjl493456442) use sync pool
192+ list = getHashList ()
193193 }
194194 list = append (list , state )
195195 l .accounts [accountHash ] = list
@@ -204,7 +204,7 @@ func (l *lookup) addLayer(diff *diffLayer) {
204204 key := storageKey (accountHash , slotHash )
205205 list , exists := l .storages [key ]
206206 if ! exists {
207- list = make ([]common. Hash , 0 , 16 ) // TODO(rjl493456442) use sync pool
207+ list = getHashList ()
208208 }
209209 list = append (list , state )
210210 l .storages [key ] = list
@@ -229,7 +229,9 @@ func removeFromList(list []common.Hash, element common.Hash) (bool, []common.Has
229229 // Mitigation: release the array if capacity exceeds threshold.
230230 list = list [1 :]
231231 if cap (list ) > 1024 {
232- list = append (make ([]common.Hash , 0 , len (list )), list ... )
232+ newList := append (make ([]common.Hash , 0 , len (list )), list ... )
233+ putHashList (list )
234+ list = newList
233235 }
234236 }
235237 return true , list
@@ -258,6 +260,7 @@ func (l *lookup) removeLayer(diff *diffLayer) error {
258260 if len (list ) != 0 {
259261 l .accounts [accountHash ] = list
260262 } else {
263+ putHashList (list )
261264 delete (l .accounts , accountHash )
262265 }
263266 }
@@ -275,6 +278,7 @@ func (l *lookup) removeLayer(diff *diffLayer) error {
275278 if len (list ) != 0 {
276279 l .storages [key ] = list
277280 } else {
281+ putHashList (list )
278282 delete (l .storages , key )
279283 }
280284 }
@@ -283,3 +287,24 @@ func (l *lookup) removeLayer(diff *diffLayer) error {
283287 })
284288 return eg .Wait ()
285289}
290+
291+ // hashListPool is not allocation-free. Since a slice header is 24 bytes and
292+ // cannot be stored directly in an interface, interface boxing is involved,
293+ // which typically incurs a 24-byte allocation. This design strikes a balance
294+ // between allocation efficiency and code simplicity. Note that it is possible
295+ // to achieve zero allocations by wrapping the []common.Hash in a struct and
296+ // storing a pointer to that struct in the sync.Pool.
297+ var hashListPool = sync.Pool {
298+ New : func () any {
299+ return make ([]common.Hash , 0 , 16 )
300+ },
301+ }
302+
303+ func getHashList () []common.Hash {
304+ l := hashListPool .Get ().([]common.Hash )
305+ return l [:0 ]
306+ }
307+
308+ func putHashList (l []common.Hash ) {
309+ hashListPool .Put (l )
310+ }
0 commit comments