core/rawdb: reduce allocations in *key

This commit is contained in:
MariusVanDerWijden 2025-10-26 20:06:57 +01:00
parent 09e36d729f
commit 04383239e5
3 changed files with 80 additions and 60 deletions

View file

@ -88,7 +88,7 @@ type NumberHash struct {
// This method considers both limits to be _inclusive_. // This method considers both limits to be _inclusive_.
func ReadAllHashesInRange(db ethdb.Iteratee, first, last uint64) []*NumberHash { func ReadAllHashesInRange(db ethdb.Iteratee, first, last uint64) []*NumberHash {
var ( var (
start = encodeBlockNumber(first) start = encodeUint64(first)
keyLength = len(headerPrefix) + 8 + 32 keyLength = len(headerPrefix) + 8 + 32
hashes = make([]*NumberHash, 0, 1+last-first) hashes = make([]*NumberHash, 0, 1+last-first)
it = db.NewIterator(headerPrefix, start) it = db.NewIterator(headerPrefix, start)
@ -155,7 +155,7 @@ func ReadHeaderNumber(db ethdb.KeyValueReader, hash common.Hash) (uint64, bool)
// WriteHeaderNumber stores the hash->number mapping. // WriteHeaderNumber stores the hash->number mapping.
func WriteHeaderNumber(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { func WriteHeaderNumber(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
key := headerNumberKey(hash) key := headerNumberKey(hash)
enc := encodeBlockNumber(number) enc := encodeUint64(number)
if err := db.Put(key, enc); err != nil { if err := db.Put(key, enc); err != nil {
log.Crit("Failed to store hash to number mapping", "err", err) log.Crit("Failed to store hash to number mapping", "err", err)
} }
@ -272,7 +272,7 @@ func ReadTxIndexTail(db ethdb.KeyValueReader) *uint64 {
// WriteTxIndexTail stores the number of oldest indexed block // WriteTxIndexTail stores the number of oldest indexed block
// into database. // into database.
func WriteTxIndexTail(db ethdb.KeyValueWriter, number uint64) { func WriteTxIndexTail(db ethdb.KeyValueWriter, number uint64) {
if err := db.Put(txIndexTailKey, encodeBlockNumber(number)); err != nil { if err := db.Put(txIndexTailKey, encodeUint64(number)); err != nil {
log.Crit("Failed to store the transaction index tail", "err", err) log.Crit("Failed to store the transaction index tail", "err", err)
} }
} }

View file

@ -130,7 +130,7 @@ func ReadPersistentStateID(db ethdb.KeyValueReader) uint64 {
// WritePersistentStateID stores the id of the persistent state into database. // WritePersistentStateID stores the id of the persistent state into database.
func WritePersistentStateID(db ethdb.KeyValueWriter, number uint64) { func WritePersistentStateID(db ethdb.KeyValueWriter, number uint64) {
if err := db.Put(persistentStateIDKey, encodeBlockNumber(number)); err != nil { if err := db.Put(persistentStateIDKey, encodeUint64(number)); err != nil {
log.Crit("Failed to store the persistent state ID", "err", err) log.Crit("Failed to store the persistent state ID", "err", err)
} }
} }

View file

@ -177,81 +177,115 @@ type LegacyTxLookupEntry struct {
Index uint64 Index uint64
} }
// encodeBlockNumber encodes a block number as big endian uint64 // encodeUint64 encodes a block number as big endian uint64
func encodeBlockNumber(number uint64) []byte { func encodeUint64(number uint64) []byte {
enc := make([]byte, 8) enc := make([]byte, 8)
binary.BigEndian.PutUint64(enc, number) binary.BigEndian.PutUint64(enc, number)
return enc return enc
} }
func encodeUint32(number uint32) []byte {
enc := make([]byte, 4)
binary.BigEndian.PutUint32(enc, number)
return enc
}
func encodeKey(input []byte, values ...[]byte) []byte {
off := 0
for _, h := range values {
off += copy(input[off:], h)
}
return input
}
// headerKeyPrefix = headerPrefix + num (uint64 big endian) // headerKeyPrefix = headerPrefix + num (uint64 big endian)
func headerKeyPrefix(number uint64) []byte { func headerKeyPrefix(number uint64) []byte {
return append(headerPrefix, encodeBlockNumber(number)...) // len(headerPrefix) + len(uint64)
buf := make([]byte, 1+8)
return encodeKey(buf, headerPrefix, encodeUint64(number))
} }
// headerKey = headerPrefix + num (uint64 big endian) + hash // headerKey = headerPrefix + num (uint64 big endian) + hash
func headerKey(number uint64, hash common.Hash) []byte { func headerKey(number uint64, hash common.Hash) []byte {
return append(append(headerPrefix, encodeBlockNumber(number)...), hash.Bytes()...) // len(headerPrefix) + len(uint64) + len(hash)
buf := make([]byte, 1+8+common.HashLength)
return encodeKey(buf, headerPrefix, encodeUint64(number), hash.Bytes())
} }
// headerHashKey = headerPrefix + num (uint64 big endian) + headerHashSuffix // headerHashKey = headerPrefix + num (uint64 big endian) + headerHashSuffix
func headerHashKey(number uint64) []byte { func headerHashKey(number uint64) []byte {
return append(append(headerPrefix, encodeBlockNumber(number)...), headerHashSuffix...) // len(headerPrefix) + len(uint64) + len(headerHashSuffix)
buf := make([]byte, 1+8+1)
return encodeKey(buf, headerPrefix, encodeUint64(number), headerHashSuffix)
} }
// headerNumberKey = headerNumberPrefix + hash // headerNumberKey = headerNumberPrefix + hash
func headerNumberKey(hash common.Hash) []byte { func headerNumberKey(hash common.Hash) []byte {
return append(headerNumberPrefix, hash.Bytes()...) buf := make([]byte, 1+common.HashLength)
return encodeKey(buf, headerNumberPrefix, hash.Bytes())
} }
// blockBodyKey = blockBodyPrefix + num (uint64 big endian) + hash // blockBodyKey = blockBodyPrefix + num (uint64 big endian) + hash
func blockBodyKey(number uint64, hash common.Hash) []byte { func blockBodyKey(number uint64, hash common.Hash) []byte {
return append(append(blockBodyPrefix, encodeBlockNumber(number)...), hash.Bytes()...) // len(blockBodyPrefix) + len(uint64) + len(hash)
buf := make([]byte, 1+8+common.HashLength)
return encodeKey(buf, blockBodyPrefix, encodeUint64(number), hash.Bytes())
} }
// blockReceiptsKey = blockReceiptsPrefix + num (uint64 big endian) + hash // blockReceiptsKey = blockReceiptsPrefix + num (uint64 big endian) + hash
func blockReceiptsKey(number uint64, hash common.Hash) []byte { func blockReceiptsKey(number uint64, hash common.Hash) []byte {
return append(append(blockReceiptsPrefix, encodeBlockNumber(number)...), hash.Bytes()...) // len(blockReceiptsPrefix) + len(uint64) + len(hash)
buf := make([]byte, 1+8+common.HashLength)
return encodeKey(buf, blockReceiptsPrefix, encodeUint64(number), hash.Bytes())
} }
// txLookupKey = txLookupPrefix + hash // txLookupKey = txLookupPrefix + hash
func txLookupKey(hash common.Hash) []byte { func txLookupKey(hash common.Hash) []byte {
return append(txLookupPrefix, hash.Bytes()...) // len(txLookupPrefix) + len(hash)
buf := make([]byte, 1+common.HashLength)
return encodeKey(buf, txLookupPrefix, hash.Bytes())
} }
// accountSnapshotKey = SnapshotAccountPrefix + hash // accountSnapshotKey = SnapshotAccountPrefix + hash
func accountSnapshotKey(hash common.Hash) []byte { func accountSnapshotKey(hash common.Hash) []byte {
return append(SnapshotAccountPrefix, hash.Bytes()...) // len(SnapshotAccountPrefix) + len(hash)
buf := make([]byte, 1+common.HashLength)
return encodeKey(buf, SnapshotAccountPrefix, hash.Bytes())
} }
// storageSnapshotKey = SnapshotStoragePrefix + account hash + storage hash // storageSnapshotKey = SnapshotStoragePrefix + account hash + storage hash
func storageSnapshotKey(accountHash, storageHash common.Hash) []byte { func storageSnapshotKey(accountHash, storageHash common.Hash) []byte {
//len(SnapshotStoragePrefix) == 1 //len(SnapshotStoragePrefix) + len(accountHash) + len(storageHash)
buf := make([]byte, 1+common.HashLength+common.HashLength) buf := make([]byte, 1+common.HashLength+common.HashLength)
n := copy(buf, SnapshotStoragePrefix) return encodeKey(buf, SnapshotStoragePrefix, accountHash.Bytes(), storageHash.Bytes())
n += copy(buf[n:], accountHash.Bytes())
copy(buf[n:], storageHash.Bytes())
return buf
} }
// storageSnapshotsKey = SnapshotStoragePrefix + account hash + storage hash // storageSnapshotsKey = SnapshotStoragePrefix + account hash
func storageSnapshotsKey(accountHash common.Hash) []byte { func storageSnapshotsKey(accountHash common.Hash) []byte {
return append(SnapshotStoragePrefix, accountHash.Bytes()...) // len(SnapshotStoragePrefix) + len(accountHash)
buf := make([]byte, 1+common.HashLength)
return encodeKey(buf, SnapshotStoragePrefix, accountHash.Bytes())
} }
// skeletonHeaderKey = skeletonHeaderPrefix + num (uint64 big endian) // skeletonHeaderKey = skeletonHeaderPrefix + num (uint64 big endian)
func skeletonHeaderKey(number uint64) []byte { func skeletonHeaderKey(number uint64) []byte {
return append(skeletonHeaderPrefix, encodeBlockNumber(number)...) // len(skeletonHeaderPrefix) + len(uint64)
buf := make([]byte, 1+8)
return encodeKey(buf, skeletonHeaderPrefix, encodeUint64(number))
} }
// preimageKey = PreimagePrefix + hash // preimageKey = PreimagePrefix + hash
func preimageKey(hash common.Hash) []byte { func preimageKey(hash common.Hash) []byte {
return append(PreimagePrefix, hash.Bytes()...) // len(PreimagePrefix) + len(hash)
buf := make([]byte, 11+common.HashLength)
return encodeKey(buf, PreimagePrefix, hash.Bytes())
} }
// codeKey = CodePrefix + hash // codeKey = CodePrefix + hash
func codeKey(hash common.Hash) []byte { func codeKey(hash common.Hash) []byte {
return append(CodePrefix, hash.Bytes()...) // len(CodePrefix) + len(hash)
buf := make([]byte, 1+common.HashLength)
return encodeKey(buf, CodePrefix, hash.Bytes())
} }
// IsCodeKey reports whether the given byte slice is the key of contract code, // IsCodeKey reports whether the given byte slice is the key of contract code,
@ -265,17 +299,23 @@ func IsCodeKey(key []byte) (bool, []byte) {
// configKey = configPrefix + hash // configKey = configPrefix + hash
func configKey(hash common.Hash) []byte { func configKey(hash common.Hash) []byte {
return append(configPrefix, hash.Bytes()...) // len(configPrefix) + len(hash)
buf := make([]byte, 16+common.HashLength)
return encodeKey(buf, configPrefix, hash.Bytes())
} }
// genesisStateSpecKey = genesisPrefix + hash // genesisStateSpecKey = genesisPrefix + hash
func genesisStateSpecKey(hash common.Hash) []byte { func genesisStateSpecKey(hash common.Hash) []byte {
return append(genesisPrefix, hash.Bytes()...) // len(genesisPrefix) + len(hash)
buf := make([]byte, 17+common.HashLength)
return encodeKey(buf, genesisPrefix, hash.Bytes())
} }
// stateIDKey = stateIDPrefix + root (32 bytes) // stateIDKey = stateIDPrefix + root (32 bytes)
func stateIDKey(root common.Hash) []byte { func stateIDKey(root common.Hash) []byte {
return append(stateIDPrefix, root.Bytes()...) // len(stateIDPrefix) + len(root)
buf := make([]byte, 1+common.HashLength)
return encodeKey(buf, stateIDPrefix, root.Bytes())
} }
// accountTrieNodeKey = TrieNodeAccountPrefix + nodePath. // accountTrieNodeKey = TrieNodeAccountPrefix + nodePath.
@ -356,8 +396,7 @@ func IsStorageTrieNode(key []byte) bool {
func filterMapRowKey(mapRowIndex uint64, base bool) []byte { func filterMapRowKey(mapRowIndex uint64, base bool) []byte {
// len(filterMapRowPrefix) + extLen // len(filterMapRowPrefix) + extLen
key := make([]byte, 4+9) key := make([]byte, 4+9)
copy(key[:4], filterMapRowPrefix) key = encodeKey(key, filterMapRowPrefix, encodeUint64(mapRowIndex))
binary.BigEndian.PutUint64(key[4:4+8], mapRowIndex)
if !base { if !base {
return key[0 : 4+8] return key[0 : 4+8]
} }
@ -368,36 +407,28 @@ func filterMapRowKey(mapRowIndex uint64, base bool) []byte {
func filterMapLastBlockKey(mapIndex uint32) []byte { func filterMapLastBlockKey(mapIndex uint32) []byte {
// len(filterMapLastBlockPrefix) + len(uint32) // len(filterMapLastBlockPrefix) + len(uint32)
key := make([]byte, 4+4) key := make([]byte, 4+4)
copy(key[:4], filterMapLastBlockPrefix) return encodeKey(key, filterMapLastBlockPrefix, encodeUint32(mapIndex))
binary.BigEndian.PutUint32(key[4:], mapIndex)
return key
} }
// filterMapBlockLVKey = filterMapBlockLVPrefix + num (uint64 big endian) // filterMapBlockLVKey = filterMapBlockLVPrefix + num (uint64 big endian)
func filterMapBlockLVKey(number uint64) []byte { func filterMapBlockLVKey(number uint64) []byte {
//len(filterMapBlockLVPrefix) + len(uint64) //len(filterMapBlockLVPrefix) + len(uint64)
key := make([]byte, 4+8) key := make([]byte, 4+8)
copy(key[:4], filterMapBlockLVPrefix) return encodeKey(key, filterMapBlockLVPrefix, encodeUint64(number))
binary.BigEndian.PutUint64(key[4:], number)
return key
} }
// accountHistoryIndexKey = StateHistoryAccountMetadataPrefix + addressHash // accountHistoryIndexKey = StateHistoryAccountMetadataPrefix + addressHash
func accountHistoryIndexKey(addressHash common.Hash) []byte { func accountHistoryIndexKey(addressHash common.Hash) []byte {
return append(StateHistoryAccountMetadataPrefix, addressHash.Bytes()...) // len(StateHistoryAccountMetadataPrefix) + len(addressHash)
buf := make([]byte, 2+common.HashLength)
return encodeKey(buf, StateHistoryAccountMetadataPrefix, addressHash.Bytes())
} }
// storageHistoryIndexKey = StateHistoryStorageMetadataPrefix + addressHash + storageHash // storageHistoryIndexKey = StateHistoryStorageMetadataPrefix + addressHash + storageHash
func storageHistoryIndexKey(addressHash common.Hash, storageHash common.Hash) []byte { func storageHistoryIndexKey(addressHash common.Hash, storageHash common.Hash) []byte {
// len(StateHistoryStorageMetadataPrefix) == 2 // len(StateHistoryStorageMetadataPrefix) + len(addressHash) + len(storageHash)
out := make([]byte, 2+2*common.HashLength) out := make([]byte, 2+2*common.HashLength)
return encodeKey(out, StateHistoryStorageMetadataPrefix, addressHash.Bytes(), storageHash.Bytes())
off := 0
off += copy(out[off:], StateHistoryStorageMetadataPrefix)
off += copy(out[off:], addressHash.Bytes())
copy(out[off:], storageHash.Bytes())
return out
} }
// trienodeHistoryIndexKey = TrienodeHistoryMetadataPrefix + addressHash + trienode path // trienodeHistoryIndexKey = TrienodeHistoryMetadataPrefix + addressHash + trienode path
@ -417,27 +448,14 @@ func trienodeHistoryIndexKey(addressHash common.Hash, path []byte) []byte {
func accountHistoryIndexBlockKey(addressHash common.Hash, blockID uint32) []byte { func accountHistoryIndexBlockKey(addressHash common.Hash, blockID uint32) []byte {
// len(StateHistoryAccountBlockPrefix) + len(common.Hash) + len(uint32) // len(StateHistoryAccountBlockPrefix) + len(common.Hash) + len(uint32)
out := make([]byte, 3+common.HashLength+4) out := make([]byte, 3+common.HashLength+4)
return encodeKey(out, StateHistoryAccountBlockPrefix, addressHash.Bytes(), encodeUint32(blockID))
off := 0
off += copy(out[off:], StateHistoryAccountBlockPrefix)
off += copy(out[off:], addressHash.Bytes())
binary.BigEndian.PutUint32(out[off:], blockID)
return out
} }
// storageHistoryIndexBlockKey = StateHistoryStorageBlockPrefix + addressHash + storageHash + blockID // storageHistoryIndexBlockKey = StateHistoryStorageBlockPrefix + addressHash + storageHash + blockID
func storageHistoryIndexBlockKey(addressHash common.Hash, storageHash common.Hash, blockID uint32) []byte { func storageHistoryIndexBlockKey(addressHash common.Hash, storageHash common.Hash, blockID uint32) []byte {
// len(StateHistoryStorageBlockPrefix) + 2*common.HashLength + len(uint32) // len(StateHistoryStorageBlockPrefix) + 2*common.HashLength + len(uint32)
out := make([]byte, 3+2*common.HashLength+4) out := make([]byte, 3+2*common.HashLength+4)
return encodeKey(out, StateHistoryStorageBlockPrefix, addressHash.Bytes(), storageHash.Bytes(), encodeUint32(blockID))
off := 0
off += copy(out[off:], StateHistoryStorageBlockPrefix)
off += copy(out[off:], addressHash.Bytes())
off += copy(out[off:], storageHash.Bytes())
binary.BigEndian.PutUint32(out[off:], blockID)
return out
} }
// trienodeHistoryIndexBlockKey = TrienodeHistoryBlockPrefix + addressHash + trienode path + blockID // trienodeHistoryIndexBlockKey = TrienodeHistoryBlockPrefix + addressHash + trienode path + blockID
@ -456,5 +474,7 @@ func trienodeHistoryIndexBlockKey(addressHash common.Hash, path []byte, blockID
// transitionStateKey = transitionStatusKey + hash // transitionStateKey = transitionStatusKey + hash
func transitionStateKey(hash common.Hash) []byte { func transitionStateKey(hash common.Hash) []byte {
return append(VerkleTransitionStatePrefix, hash.Bytes()...) // len(VerkleTransitionStatePrefix) + len(hash)
buf := make([]byte, 24+common.HashLength)
return encodeKey(buf, VerkleTransitionStatePrefix, hash.Bytes())
} }