mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2025-01-03 09:37:38 +00:00
Optimize resolver cached (#404)
* remove allocations related to "remove incarnation" actions * invalidate startKeyNoInc when startKey changed * dbutils.RemoveIncarnationFromKey - doesn't do allocation
This commit is contained in:
parent
b0f962e3ba
commit
8d7e1e9374
@ -119,14 +119,15 @@ func DecodeIncarnation(buf []byte) uint64 {
|
||||
return incarnation ^ ^uint64(0)
|
||||
}
|
||||
|
||||
func RemoveIncarnationFromKey(storageKey []byte) []byte {
|
||||
if len(storageKey) <= common.HashLength {
|
||||
return storageKey
|
||||
func RemoveIncarnationFromKey(key []byte, buf *[]byte) {
|
||||
tmp := *buf
|
||||
if len(key) <= common.HashLength {
|
||||
tmp = append(tmp, key...)
|
||||
} else {
|
||||
tmp = append(tmp, key[:common.HashLength]...)
|
||||
tmp = append(tmp, key[common.HashLength+8:]...)
|
||||
}
|
||||
buf := make([]byte, 0, common.HashLength*2)
|
||||
buf = append(buf, storageKey[:common.HashLength]...)
|
||||
buf = append(buf, storageKey[common.HashLength+8:]...)
|
||||
return buf
|
||||
*buf = tmp
|
||||
}
|
||||
|
||||
// Key + blockNum
|
||||
|
@ -294,6 +294,9 @@ func ClearTombstonesForReCreatedAccount(db ethdb.MinDatabase, addrHash common.Ha
|
||||
return nil
|
||||
}
|
||||
|
||||
buf := pool.GetBuffer(256)
|
||||
defer pool.PutBuffer(buf)
|
||||
|
||||
incarnation := dbutils.DecodeIncarnation(k[common.HashLength : common.HashLength+8])
|
||||
for ; incarnation > 0; incarnation-- {
|
||||
accWithInc := dbutils.GenerateStoragePrefix(addrHash, incarnation)
|
||||
@ -306,8 +309,9 @@ func ClearTombstonesForReCreatedAccount(db ethdb.MinDatabase, addrHash common.Ha
|
||||
break
|
||||
}
|
||||
|
||||
kNoInc := dbutils.RemoveIncarnationFromKey(k)
|
||||
toPut = append(toPut, common.CopyBytes(kNoInc[:common.HashLength+1]))
|
||||
buf.Reset()
|
||||
dbutils.RemoveIncarnationFromKey(k, &buf.B)
|
||||
toPut = append(toPut, common.CopyBytes(buf.B[:common.HashLength+1]))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@ -412,6 +416,9 @@ func ClearTombstonesForNewStorage(db ethdb.MinDatabase, storageKeyNoInc []byte)
|
||||
kWithInc.B = append(kWithInc.B, storageK[:common.HashLength+8]...)
|
||||
kWithInc.B = append(kWithInc.B, storageKeyNoInc[common.HashLength:]...)
|
||||
|
||||
buf := pool.GetBuffer(256)
|
||||
defer pool.PutBuffer(buf)
|
||||
|
||||
for i := common.HashLength + 1; i < len(storageKeyNoInc)-1; i++ { // +1 because first step happened during account re-creation
|
||||
tombStone, _ := interBucket.Get(storageKeyNoInc[:i])
|
||||
foundTombstone := tombStone != nil && len(tombStone) == 0
|
||||
@ -431,7 +438,9 @@ func ClearTombstonesForNewStorage(db ethdb.MinDatabase, storageKeyNoInc []byte)
|
||||
continue
|
||||
}
|
||||
|
||||
toPut = append(toPut, dbutils.RemoveIncarnationFromKey(storageK[:i+1+8]))
|
||||
buf.Reset()
|
||||
dbutils.RemoveIncarnationFromKey(storageK[:i+1+8], &buf.B)
|
||||
toPut = append(toPut, common.CopyBytes(buf.B))
|
||||
}
|
||||
toDelete = append(toDelete, common.CopyBytes(storageKeyNoInc[:i]))
|
||||
break
|
||||
|
@ -343,9 +343,16 @@ func (tr *ResolverStatefulCached) MultiWalk2(db *bolt.DB, blockNr uint64, bucket
|
||||
keyAsNibbles := pool.GetBuffer(256)
|
||||
defer pool.PutBuffer(keyAsNibbles)
|
||||
|
||||
startKeyNoInc := pool.GetBuffer(common.HashLength * 2)
|
||||
defer pool.PutBuffer(startKeyNoInc)
|
||||
|
||||
rangeIdx := 0 // What is the current range we are extracting
|
||||
fixedbytes, mask := ethdb.Bytesmask(fixedbits[rangeIdx])
|
||||
startkey := startkeys[rangeIdx]
|
||||
|
||||
startKeyNoInc.Reset()
|
||||
dbutils.RemoveIncarnationFromKey(startkey, &startKeyNoInc.B)
|
||||
|
||||
err := db.View(func(tx *bolt.Tx) error {
|
||||
cacheBucket := tx.Bucket(dbutils.IntermediateTrieHashBucket)
|
||||
if cacheBucket == nil {
|
||||
@ -360,7 +367,7 @@ func (tr *ResolverStatefulCached) MultiWalk2(db *bolt.DB, blockNr uint64, bucket
|
||||
c := b.Cursor()
|
||||
|
||||
k, v := c.Seek(startkey)
|
||||
cacheK, cacheV := cache.Seek(dbutils.RemoveIncarnationFromKey(startkey))
|
||||
cacheK, cacheV := cache.Seek(startKeyNoInc.B)
|
||||
|
||||
var minKey []byte
|
||||
var fromCache bool
|
||||
@ -391,7 +398,7 @@ func (tr *ResolverStatefulCached) MultiWalk2(db *bolt.DB, blockNr uint64, bucket
|
||||
startKeyIndex = minInt(len(startkey), fixedbytes-1-8)
|
||||
cmp = bytes.Compare(minKey[:minKeyIndex], startkey[:startKeyIndex])
|
||||
} else if fromCache && fixedbytes > 40 {
|
||||
cmp = bytes.Compare(minKey[:minKeyIndex], dbutils.RemoveIncarnationFromKey(startkey[:startKeyIndex]))
|
||||
cmp = bytes.Compare(minKey[:minKeyIndex], startKeyNoInc.B[:startKeyIndex])
|
||||
} else {
|
||||
cmp = bytes.Compare(minKey[:minKeyIndex], startkey[:startKeyIndex])
|
||||
}
|
||||
@ -411,7 +418,7 @@ func (tr *ResolverStatefulCached) MultiWalk2(db *bolt.DB, blockNr uint64, bucket
|
||||
}
|
||||
if cmp < 0 {
|
||||
k, v = c.SeekTo(startkey)
|
||||
cacheK, cacheV = cache.SeekTo(dbutils.RemoveIncarnationFromKey(startkey))
|
||||
cacheK, cacheV = cache.SeekTo(startKeyNoInc.B)
|
||||
// for Address bucket, skip cache keys longer than 31 bytes
|
||||
if isAccountBucket && len(cacheK) > maxAccountKeyLen {
|
||||
for len(cacheK) > maxAccountKeyLen {
|
||||
@ -430,6 +437,8 @@ func (tr *ResolverStatefulCached) MultiWalk2(db *bolt.DB, blockNr uint64, bucket
|
||||
}
|
||||
fixedbytes, mask = ethdb.Bytesmask(fixedbits[rangeIdx])
|
||||
startkey = startkeys[rangeIdx]
|
||||
startKeyNoInc.Reset()
|
||||
dbutils.RemoveIncarnationFromKey(startkey, &startKeyNoInc.B)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -495,11 +504,18 @@ func (tr *ResolverStatefulCached) MultiWalk2(db *bolt.DB, blockNr uint64, bucket
|
||||
continue
|
||||
}
|
||||
|
||||
if isAccountBucket {
|
||||
if isAccountBucket || len(cacheK) <= common.HashLength {
|
||||
k, v = c.Seek(next)
|
||||
} else {
|
||||
// skip subtree - can't .Seek because storage bucket has incarnation in keys
|
||||
for k, v = c.Next(); bytes.HasPrefix(dbutils.RemoveIncarnationFromKey(k), cacheK); k, v = c.Next() {
|
||||
for k, v = c.Next(); k != nil; k, v = c.Next() {
|
||||
matchAcc := bytes.HasPrefix(k[:common.HashLength], next[:common.HashLength])
|
||||
// don't check incarnation ...
|
||||
matchStorage := bytes.HasPrefix(k[common.HashLength+8:], next[common.HashLength:])
|
||||
|
||||
if matchAcc && matchStorage {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user