diff --git a/lib/mergeset/encoding.go b/lib/mergeset/encoding.go index f57f4f4e3..8cb57082c 100644 --- a/lib/mergeset/encoding.go +++ b/lib/mergeset/encoding.go @@ -540,6 +540,17 @@ func putLensBuffer(lb *lensBuffer) { lensBufferPool.Put(lb) } -func newInmemoryBlock() *inmemoryBlock { - return &inmemoryBlock{} +func getInmemoryBlock() *inmemoryBlock { + v := ibPool.Get() + if v == nil { + return &inmemoryBlock{} + } + return v.(*inmemoryBlock) } + +func putInmemoryBlock(ib *inmemoryBlock) { + ib.Reset() + ibPool.Put(ib) +} + +var ibPool sync.Pool diff --git a/lib/mergeset/part_search.go b/lib/mergeset/part_search.go index d2a8a1116..8671561b6 100644 --- a/lib/mergeset/part_search.go +++ b/lib/mergeset/part_search.go @@ -316,7 +316,7 @@ func (ps *partSearch) readInmemoryBlock(bh *blockHeader) (*inmemoryBlock, error) ps.sb.lensData = bytesutil.Resize(ps.sb.lensData, int(bh.lensBlockSize)) ps.p.lensFile.MustReadAt(ps.sb.lensData, int64(bh.lensBlockOffset)) - ib := newInmemoryBlock() + ib := getInmemoryBlock() if err := ib.UnmarshalData(&ps.sb, bh.firstItem, bh.commonPrefix, bh.itemsCount, bh.marshalType); err != nil { return nil, fmt.Errorf("cannot unmarshal storage block with %d items: %w", bh.itemsCount, err) } diff --git a/lib/mergeset/table.go b/lib/mergeset/table.go index 6a9eb7bed..ba12ada94 100644 --- a/lib/mergeset/table.go +++ b/lib/mergeset/table.go @@ -182,15 +182,16 @@ func (ris *rawItemsShard) addItems(tb *Table, items [][]byte) error { ris.mu.Lock() ibs := ris.ibs if len(ibs) == 0 { - ib := newInmemoryBlock() + ib := getInmemoryBlock() ibs = append(ibs, ib) ris.ibs = ibs } ib := ibs[len(ibs)-1] for _, item := range items { if !ib.Add(item) { - ib = newInmemoryBlock() + ib = getInmemoryBlock() if !ib.Add(item) { + putInmemoryBlock(ib) err = fmt.Errorf("cannot insert an item %q into an empty inmemoryBlock; it looks like the item is too large? len(item)=%d", item, len(item)) break } @@ -674,13 +675,13 @@ func (tb *Table) mergeRawItemsBlocks(blocksToMerge []*inmemoryBlock) { func (tb *Table) mergeInmemoryBlocks(blocksToMerge []*inmemoryBlock) *partWrapper { // Convert blocksToMerge into inmemoryPart's mps := make([]*inmemoryPart, 0, len(blocksToMerge)) - for i, ib := range blocksToMerge { + for _, ib := range blocksToMerge { if len(ib.items) == 0 { continue } mp := getInmemoryPart() mp.Init(ib) - blocksToMerge[i] = nil + putInmemoryBlock(ib) mps = append(mps, mp) } if len(mps) == 0 {