From 5c935e71fa3a00b8e3a3f9a2dde522f4aa714f7b Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Sat, 14 Feb 2026 23:39:17 +0100 Subject: [PATCH] index: also preallocate hashed array tree --- internal/repository/index/indexmap.go | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/internal/repository/index/indexmap.go b/internal/repository/index/indexmap.go index af836a97d..159abe7fe 100644 --- a/internal/repository/index/indexmap.go +++ b/internal/repository/index/indexmap.go @@ -166,6 +166,8 @@ func (m *indexMap) preallocate(numEntries int) { e.next = m.buckets[h] m.buckets[h] = bloomInsertID(i, e.next, e.id) } + + m.blockList.preallocate(uint(numEntries)) } func (m *indexMap) hash(id restic.ID) uint { @@ -300,9 +302,9 @@ func (h *hashedArrayTree) Size() uint { return h.size } -func (h *hashedArrayTree) grow() { - idx, subIdx := h.index(h.size) - if int(idx) == len(h.blockList) { +func (h *hashedArrayTree) preallocate(numEntries uint) { + idx, _ := h.index(numEntries - 1) + for int(idx) >= len(h.blockList) { // blockList is too short -> double list and block size h.blockSize *= 2 h.mask = h.mask*2 + 1 @@ -314,15 +316,26 @@ func (h *hashedArrayTree) grow() { // pairwise merging of blocks for i := 0; i < len(oldBlocks); i += 2 { + if oldBlocks[i] == nil && oldBlocks[i+1] == nil { + // merged all blocks with data. Grow will allocate the block later on + break + } block := make([]indexEntry, 0, h.blockSize) block = append(block, oldBlocks[i]...) block = append(block, oldBlocks[i+1]...) - h.blockList[i/2] = block + // make sure to set the correct length as not all old blocks may contain entries yet + h.blockList[i/2] = block[0:h.blockSize] // allow GC oldBlocks[i] = nil oldBlocks[i+1] = nil } } +} + +func (h *hashedArrayTree) grow() { + h.preallocate(h.size + 1) + + idx, subIdx := h.index(h.size) if subIdx == 0 { // new index entry batch h.blockList[idx] = make([]indexEntry, h.blockSize)