diff --git a/head.go b/head.go index 917e2b071..cbc8661f8 100644 --- a/head.go +++ b/head.go @@ -1096,25 +1096,30 @@ func (h *headIndexReader) Postings(name, value string) (index.Postings, error) { } func (h *headIndexReader) SortedPostings(p index.Postings) index.Postings { - ep := make([]uint64, 0, 128) + series := make([]*memSeries, 0, 128) + // Fetch all the series only once. for p.Next() { - ep = append(ep, p.At()) + s := h.head.series.getByID(p.At()) + if s == nil { + level.Debug(h.head.logger).Log("msg", "looked up series not found") + } else { + series = append(series, s) + } } if err := p.Err(); err != nil { return index.ErrPostings(errors.Wrap(err, "expand postings")) } - sort.Slice(ep, func(i, j int) bool { - a := h.head.series.getByID(ep[i]) - b := h.head.series.getByID(ep[j]) - - if a == nil || b == nil { - level.Debug(h.head.logger).Log("msg", "looked up series not found") - return false - } - return labels.Compare(a.lset, b.lset) < 0 + sort.Slice(series, func(i, j int) bool { + return labels.Compare(series[i].lset, series[j].lset) < 0 }) + + // Convert back to list. + ep := make([]uint64, 0, len(series)) + for _, p := range series { + ep = append(ep, p.ref) + } return index.NewListPostings(ep) } diff --git a/head_bench_test.go b/head_bench_test.go index 4b80193b2..b511667f5 100644 --- a/head_bench_test.go +++ b/head_bench_test.go @@ -57,7 +57,7 @@ func BenchmarkHeadPostingForMatchers(b *testing.B) { defer h.Close() // TODO: vary number of series - for i := 0; i < 100; i++ { + for i := 0; i < 1000000; i++ { h.getOrCreate(uint64(i), labels.FromStrings("a", strconv.Itoa(i))) }