trie: stacktrie allocation reduction via key scratchspace

This commit is contained in:
Martin Holst Swende 2024-11-11 14:20:22 +01:00
parent 5b6a6e4986
commit 4eb7032c97
No known key found for this signature in database
GPG Key ID: 683B438C05A5DDF0
2 changed files with 27 additions and 2 deletions

View File

@ -104,6 +104,17 @@ func keybytesToHex(str []byte) []byte {
return nibbles
}
// writeHexKey writes the hexkey into the given slice.
// OBS! This method omits the termination flag.
// OBS! The dst slice must be at least 2x as large as the key
func writeHexKey(dst []byte, key []byte) {
_ = dst[2*len(key)-1]
for i, b := range key {
dst[i*2] = b / 16
dst[i*2+1] = b % 16
}
}
// hexToKeybytes turns hex nibbles into key bytes.
// This can only be used for keys of even length.
func hexToKeybytes(hex []byte) []byte {

View File

@ -47,6 +47,8 @@ type StackTrie struct {
h *hasher
last []byte
onTrieNode OnTrieNode
keyScratch []byte
}
// NewStackTrie allocates and initializes an empty trie. The committed nodes
@ -64,7 +66,18 @@ func (t *StackTrie) Update(key, value []byte) error {
if len(value) == 0 {
return errors.New("trying to insert empty (deletion)")
}
k := t.TrieKey(key)
var k []byte
{
// We can reuse the key scratch area, but only if the insert-method
// never holds on to it.
if cap(t.keyScratch) < 2*len(key) { // realloc to ensure sufficient cap
t.keyScratch = make([]byte, 2*len(key), 2*len(key))
}
// resize to ensure correct size
t.keyScratch = t.keyScratch[:2*len(key)]
writeHexKey(t.keyScratch, key)
k = t.keyScratch
}
if bytes.Compare(t.last, k) >= 0 {
return errors.New("non-ascending key order")
}
@ -152,6 +165,7 @@ func (n *stNode) getDiffIndex(key []byte) int {
// Helper function to that inserts a (key, value) pair into
// the trie.
// The key is not retained by this method, but always copied if needed.
func (t *StackTrie) insert(st *stNode, key, value []byte, path []byte) {
switch st.typ {
case branchNode: /* Branch */
@ -283,7 +297,7 @@ func (t *StackTrie) insert(st *stNode, key, value []byte, path []byte) {
case emptyNode: /* Empty */
st.typ = leafNode
st.key = key
st.key = append(st.key, key...)
st.val = value
case hashedNode: