From 596d990eb95198f7d0fc19353b052622587f8895 Mon Sep 17 00:00:00 2001 From: Steve Yen Date: Tue, 27 Mar 2018 13:57:46 -0700 Subject: [PATCH] scorch zap optimize when zero hits Instead of allocating brand-new empty postingsList/Iterator instances, reuse some empty singletons. --- index/scorch/segment/zap/dict.go | 8 +++++++- index/scorch/segment/zap/posting.go | 13 +++++++++++++ index/scorch/segment/zap/segment.go | 2 +- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/index/scorch/segment/zap/dict.go b/index/scorch/segment/zap/dict.go index 38b4faca..049ebb36 100644 --- a/index/scorch/segment/zap/dict.go +++ b/index/scorch/segment/zap/dict.go @@ -39,6 +39,9 @@ func (d *Dictionary) PostingsList(term string, except *roaring.Bitmap) (segment. func (d *Dictionary) postingsList(term []byte, except *roaring.Bitmap, rv *PostingsList) (*PostingsList, error) { if d.fst == nil { + if rv == nil || rv == emptyPostingsList { + return emptyPostingsList, nil + } return d.postingsListInit(rv, except), nil } @@ -47,6 +50,9 @@ func (d *Dictionary) postingsList(term []byte, except *roaring.Bitmap, rv *Posti return nil, fmt.Errorf("vellum err: %v", err) } if !exists { + if rv == nil || rv == emptyPostingsList { + return emptyPostingsList, nil + } return d.postingsListInit(rv, except), nil } @@ -65,7 +71,7 @@ func (d *Dictionary) postingsListFromOffset(postingsOffset uint64, except *roari } func (d *Dictionary) postingsListInit(rv *PostingsList, except *roaring.Bitmap) *PostingsList { - if rv == nil { + if rv == nil || rv == emptyPostingsList { rv = &PostingsList{} } else { postings := rv.postings diff --git a/index/scorch/segment/zap/posting.go b/index/scorch/segment/zap/posting.go index 6b9e1a53..c0c39571 100644 --- a/index/scorch/segment/zap/posting.go +++ b/index/scorch/segment/zap/posting.go @@ -109,6 +109,9 @@ type PostingsList struct { normBits1Hit uint64 } +// represents an immutable, empty postings list +var emptyPostingsList = &PostingsList{} + func (p *PostingsList) Size() int { sizeInBytes := reflectStaticSizePostingsList + size.SizeOfPtr @@ -132,6 +135,10 @@ func (p *PostingsList) OrInto(receiver *roaring.Bitmap) { // Iterator returns an iterator for this postings list func (p *PostingsList) Iterator(includeFreq, includeNorm, includeLocs bool) segment.PostingsIterator { + if p.normBits1Hit == 0 && p.postings == nil { + return emptyPostingsIterator + } + return p.iterator(includeFreq, includeNorm, includeLocs, nil) } @@ -341,6 +348,8 @@ type PostingsIterator struct { includeLocs bool } +var emptyPostingsIterator = &PostingsIterator{} + func (i *PostingsIterator) Size() int { sizeInBytes := reflectStaticSizePostingsIterator + size.SizeOfPtr + len(i.currChunkFreqNorm) + @@ -589,6 +598,10 @@ func (i *PostingsIterator) nextBytes() ( } func (i *PostingsIterator) Advance(docNumber uint64) (segment.Posting, error) { + if i.postings == nil { + return nil, nil + } + // check if we are already there if i.next.Number() == docNumber { return &i.next, nil diff --git a/index/scorch/segment/zap/segment.go b/index/scorch/segment/zap/segment.go index 3a3fd02e..58f8bee0 100644 --- a/index/scorch/segment/zap/segment.go +++ b/index/scorch/segment/zap/segment.go @@ -373,7 +373,7 @@ func (s *SegmentBase) DocNumbers(ids []string) (*roaring.Bitmap, error) { return nil, err } - var postingsList *PostingsList + postingsList := emptyPostingsList for _, id := range ids { postingsList, err = idDict.postingsList([]byte(id), nil, postingsList) if err != nil {