diff --git a/go.mod b/go.mod index bce5da214..7106d773f 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/blevesearch/go-porterstemmer v1.0.3 github.com/blevesearch/goleveldb v1.0.1 github.com/blevesearch/gtreap v0.1.1 - github.com/blevesearch/scorch_segment_api/v2 v2.4.10 + github.com/blevesearch/scorch_segment_api/v2 v2.4.11-0.20260915175815-2512945d4649 github.com/blevesearch/segment v0.9.1 github.com/blevesearch/snowball v0.6.1 github.com/blevesearch/snowballstem v0.9.0 diff --git a/go.sum b/go.sum index 92dce1c72..3ed5f74d5 100644 --- a/go.sum +++ b/go.sum @@ -21,6 +21,8 @@ github.com/blevesearch/mmap-go v1.2.0 h1:l33nNKPFcBjJUMwem6sAYJPUzhUCABoK9FxZDGi github.com/blevesearch/mmap-go v1.2.0/go.mod h1:Vd6+20GBhEdwJnU1Xohgt88XCD/CTWcqbCNxkZpyBo0= github.com/blevesearch/scorch_segment_api/v2 v2.4.10 h1:C3873+iWZ0YJM2ijaSHhJJzSvD4x1k+5UaQdGygZVhM= github.com/blevesearch/scorch_segment_api/v2 v2.4.10/go.mod h1:WUUkAocbkDlNK/kgAE13NvS9oxe+u618mYZ8sOvcCc4= +github.com/blevesearch/scorch_segment_api/v2 v2.4.11-0.20260915175815-2512945d4649 h1:SZBy+klSH8iu9U4llxUreOgN9PM6Pddh+t9ClKsPTw0= +github.com/blevesearch/scorch_segment_api/v2 v2.4.11-0.20260915175815-2512945d4649/go.mod h1:WUUkAocbkDlNK/kgAE13NvS9oxe+u618mYZ8sOvcCc4= github.com/blevesearch/segment v0.9.1 h1:+dThDy+Lvgj5JMxhmOVlgFfkUtZV2kw49xax4+jTfSU= github.com/blevesearch/segment v0.9.1/go.mod h1:zN21iLm7+GnBHWTao9I+Au/7MBiL8pPFtJBJTsk6kQw= github.com/blevesearch/snowball v0.6.1 h1:cDYjn/NCH+wwt2UdehaLpr2e4BwLIjN4V/TdLsL+B5A= diff --git a/index/scorch/snapshot_index.go b/index/scorch/snapshot_index.go index a363ecb71..fb0a14a8b 100644 --- a/index/scorch/snapshot_index.go +++ b/index/scorch/snapshot_index.go @@ -622,6 +622,18 @@ func (is *IndexSnapshot) InternalID(id string) (rv index.IndexInternalID, err er return next.ID, nil } +// releasePostings returns v to its implementation's internal pool if it +// opts into segment.Releasable. This is an optional capability, the same +// idiom as segment.OptimizablePostingsIterator: most segment.PostingsList/ +// PostingsIterator values built by query optimization (e.g. the unadorned +// iterators in unadorned.go) don't back onto pooled memory and this is a +// no-op for them. +func releasePostings(v interface{}) { + if rel, ok := v.(segment.Releasable); ok { + rel.Release() + } +} + func (is *IndexSnapshot) TermFieldReader(ctx context.Context, term []byte, field string, includeFreq, includeNorm, includeTermVectors bool, ) (index.TermFieldReader, error) { @@ -684,8 +696,9 @@ func (is *IndexSnapshot) TermFieldReader(ctx context.Context, term []byte, field var prevBytesReadPL uint64 if rv.postings[i] != nil { prevBytesReadPL = rv.postings[i].BytesRead() + releasePostings(rv.postings[i]) } - pl, err := rv.dicts[i].PostingsList(term, s.deleted, rv.postings[i]) + pl, err := rv.dicts[i].PostingsList(term, s.deleted, nil) if err != nil { return nil, err } @@ -694,8 +707,9 @@ func (is *IndexSnapshot) TermFieldReader(ctx context.Context, term []byte, field var prevBytesReadItr uint64 if rv.iterators[i] != nil { prevBytesReadItr = rv.iterators[i].BytesRead() + releasePostings(rv.iterators[i]) } - rv.iterators[i] = pl.Iterator(includeFreq, includeNorm, includeTermVectors, rv.iterators[i]) + rv.iterators[i] = pl.Iterator(includeFreq, includeNorm, includeTermVectors, nil) if bytesRead := rv.postings[i].BytesRead(); prevBytesReadPL < bytesRead { rv.incrementBytesRead(bytesRead - prevBytesReadPL) diff --git a/index/scorch/snapshot_segment.go b/index/scorch/snapshot_segment.go index 806ca2f39..ab4e6e7d9 100644 --- a/index/scorch/snapshot_segment.go +++ b/index/scorch/snapshot_segment.go @@ -243,14 +243,20 @@ func (cfd *cachedFieldDocs) prepareField(field string, ss *SegmentSnapshot) { next, err := dictItr.Next() for err == nil && next != nil { var err1 error - postings, err1 = dict.PostingsList([]byte(next.Term), nil, postings) + if postings != nil { + releasePostings(postings) + } + postings, err1 = dict.PostingsList([]byte(next.Term), nil, nil) if err1 != nil { cfd.err = err1 return } cfd.size += uint64(size.SizeOfUint64) /* map key */ - postingsItr = postings.Iterator(false, false, false, postingsItr) + if postingsItr != nil { + releasePostings(postingsItr) + } + postingsItr = postings.Iterator(false, false, false, nil) nextPosting, err2 := postingsItr.Next() for err2 == nil && nextPosting != nil { docNum := nextPosting.Number()