From fe90dcccffec8596ff3901b943aef5e1982172d6 Mon Sep 17 00:00:00 2001 From: Oleg Zaytsev Date: Mon, 9 Oct 2023 17:25:18 +0200 Subject: [PATCH] Revert ListPostings change (#12955) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reverts change from https://github.com/prometheus/prometheus/pull/12906 The benchmarks show that it's slower when intersecting, which is a common usage for ListPostings (when intersecting matchers from Head) (old is before #12906, new is #12906): │ old │ new │ │ sec/op │ sec/op vs base │ Intersect/LongPostings1-16 20.54µ ± 1% 21.11µ ± 1% +2.76% (p=0.000 n=20) Intersect/LongPostings2-16 51.03m ± 1% 52.40m ± 2% +2.69% (p=0.000 n=20) Intersect/ManyPostings-16 194.2m ± 3% 332.1m ± 1% +71.00% (p=0.000 n=20) geomean 5.882m 7.161m +21.74% Signed-off-by: Oleg Zaytsev --- tsdb/index/postings.go | 35 ++++++++++++++++++++--------------- tsdb/index/postings_test.go | 2 ++ 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/tsdb/index/postings.go b/tsdb/index/postings.go index 2132014ec8..f79a8d4cfc 100644 --- a/tsdb/index/postings.go +++ b/tsdb/index/postings.go @@ -748,7 +748,7 @@ func (rp *removedPostings) Err() error { // ListPostings implements the Postings interface over a plain list. type ListPostings struct { list []storage.SeriesRef - pos int + cur storage.SeriesRef } func NewListPostings(list []storage.SeriesRef) Postings { @@ -760,34 +760,39 @@ func newListPostings(list ...storage.SeriesRef) *ListPostings { } func (it *ListPostings) At() storage.SeriesRef { - return it.list[it.pos-1] + return it.cur } func (it *ListPostings) Next() bool { - if it.pos < len(it.list) { - it.pos++ + if len(it.list) > 0 { + it.cur = it.list[0] + it.list = it.list[1:] return true } + it.cur = 0 return false } func (it *ListPostings) Seek(x storage.SeriesRef) bool { - if it.pos == 0 { - it.pos++ - } - if it.pos > len(it.list) { - return false - } // If the current value satisfies, then return. - if it.list[it.pos-1] >= x { + if it.cur >= x { return true } + if len(it.list) == 0 { + return false + } // Do binary search between current position and end. - it.pos = sort.Search(len(it.list[it.pos-1:]), func(i int) bool { - return it.list[i+it.pos-1] >= x - }) + it.pos - return it.pos-1 < len(it.list) + i := sort.Search(len(it.list), func(i int) bool { + return it.list[i] >= x + }) + if i < len(it.list) { + it.cur = it.list[i] + it.list = it.list[i+1:] + return true + } + it.list = nil + return false } func (it *ListPostings) Err() error { diff --git a/tsdb/index/postings_test.go b/tsdb/index/postings_test.go index f0f3bb75a8..783b5f84fc 100644 --- a/tsdb/index/postings_test.go +++ b/tsdb/index/postings_test.go @@ -1242,6 +1242,8 @@ func TestListPostings(t *testing.T) { }) } +// BenchmarkListPostings benchmarks ListPostings by iterating Next/At sequentially. +// See also BenchmarkIntersect as it performs more `At` calls than `Next` calls when intersecting. func BenchmarkListPostings(b *testing.B) { const maxCount = 1e6 input := make([]storage.SeriesRef, maxCount)