2017-04-10 11:59:45 -07:00
|
|
|
// Copyright 2017 The Prometheus Authors
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
2016-12-10 09:08:50 -08:00
|
|
|
package tsdb
|
|
|
|
|
2016-12-13 06:26:58 -08:00
|
|
|
import (
|
2017-08-05 04:31:48 -07:00
|
|
|
"sort"
|
2016-12-14 06:39:23 -08:00
|
|
|
"strings"
|
2019-05-27 04:24:46 -07:00
|
|
|
"unicode/utf8"
|
2016-12-13 06:26:58 -08:00
|
|
|
|
2017-10-09 06:21:46 -07:00
|
|
|
"github.com/pkg/errors"
|
2019-11-18 11:53:33 -08:00
|
|
|
"github.com/prometheus/prometheus/pkg/labels"
|
2020-02-06 07:58:38 -08:00
|
|
|
"github.com/prometheus/prometheus/storage"
|
2019-08-13 01:34:14 -07:00
|
|
|
"github.com/prometheus/prometheus/tsdb/chunkenc"
|
|
|
|
"github.com/prometheus/prometheus/tsdb/chunks"
|
|
|
|
tsdb_errors "github.com/prometheus/prometheus/tsdb/errors"
|
|
|
|
"github.com/prometheus/prometheus/tsdb/index"
|
2019-09-19 02:15:41 -07:00
|
|
|
"github.com/prometheus/prometheus/tsdb/tombstones"
|
2016-12-13 06:26:58 -08:00
|
|
|
)
|
2016-12-12 10:12:55 -08:00
|
|
|
|
2017-01-06 03:37:28 -08:00
|
|
|
// querier aggregates querying results from time blocks within
|
2017-01-05 23:08:02 -08:00
|
|
|
// a single partition.
|
2017-01-06 03:37:28 -08:00
|
|
|
type querier struct {
|
2020-02-06 07:58:38 -08:00
|
|
|
blocks []storage.Querier
|
2016-12-13 06:26:58 -08:00
|
|
|
}
|
|
|
|
|
2020-02-06 07:58:38 -08:00
|
|
|
func (q *querier) LabelValues(n string) ([]string, storage.Warnings, error) {
|
2017-06-12 23:25:13 -07:00
|
|
|
return q.lvals(q.blocks, n)
|
|
|
|
}
|
|
|
|
|
2018-11-16 10:02:24 -08:00
|
|
|
// LabelNames returns all the unique label names present querier blocks.
|
2020-02-06 07:58:38 -08:00
|
|
|
func (q *querier) LabelNames() ([]string, storage.Warnings, error) {
|
2018-11-16 10:02:24 -08:00
|
|
|
labelNamesMap := make(map[string]struct{})
|
2020-02-06 07:58:38 -08:00
|
|
|
var ws storage.Warnings
|
2018-11-16 10:02:24 -08:00
|
|
|
for _, b := range q.blocks {
|
2020-02-06 07:58:38 -08:00
|
|
|
names, w, err := b.LabelNames()
|
|
|
|
ws = append(ws, w...)
|
2018-11-16 10:02:24 -08:00
|
|
|
if err != nil {
|
2020-02-06 07:58:38 -08:00
|
|
|
return nil, ws, errors.Wrap(err, "LabelNames() from Querier")
|
2018-11-16 10:02:24 -08:00
|
|
|
}
|
|
|
|
for _, name := range names {
|
|
|
|
labelNamesMap[name] = struct{}{}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
labelNames := make([]string, 0, len(labelNamesMap))
|
|
|
|
for name := range labelNamesMap {
|
|
|
|
labelNames = append(labelNames, name)
|
|
|
|
}
|
|
|
|
sort.Strings(labelNames)
|
|
|
|
|
2020-02-06 07:58:38 -08:00
|
|
|
return labelNames, ws, nil
|
2018-11-16 10:02:24 -08:00
|
|
|
}
|
|
|
|
|
2020-02-06 07:58:38 -08:00
|
|
|
func (q *querier) lvals(qs []storage.Querier, n string) ([]string, storage.Warnings, error) {
|
2017-06-12 23:25:13 -07:00
|
|
|
if len(qs) == 0 {
|
2020-02-06 07:58:38 -08:00
|
|
|
return nil, nil, nil
|
2017-03-07 02:29:20 -08:00
|
|
|
}
|
2017-06-12 23:25:13 -07:00
|
|
|
if len(qs) == 1 {
|
|
|
|
return qs[0].LabelValues(n)
|
|
|
|
}
|
|
|
|
l := len(qs) / 2
|
2020-02-06 07:58:38 -08:00
|
|
|
|
|
|
|
var ws storage.Warnings
|
|
|
|
s1, w, err := q.lvals(qs[:l], n)
|
|
|
|
ws = append(ws, w...)
|
2016-12-19 03:26:25 -08:00
|
|
|
if err != nil {
|
2020-02-06 07:58:38 -08:00
|
|
|
return nil, ws, err
|
2016-12-19 03:26:25 -08:00
|
|
|
}
|
2020-02-06 07:58:38 -08:00
|
|
|
s2, ws, err := q.lvals(qs[l:], n)
|
|
|
|
ws = append(ws, w...)
|
2017-06-12 23:25:13 -07:00
|
|
|
if err != nil {
|
2020-02-06 07:58:38 -08:00
|
|
|
return nil, ws, err
|
2016-12-19 03:26:25 -08:00
|
|
|
}
|
2020-02-06 07:58:38 -08:00
|
|
|
return mergeStrings(s1, s2), ws, nil
|
2016-12-14 09:38:46 -08:00
|
|
|
}
|
|
|
|
|
2020-02-06 07:58:38 -08:00
|
|
|
func (q *querier) Select(p *storage.SelectParams, ms ...*labels.Matcher) (storage.SeriesSet, storage.Warnings, error) {
|
2020-01-17 03:21:44 -08:00
|
|
|
if len(q.blocks) != 1 {
|
2020-02-06 07:58:38 -08:00
|
|
|
return q.SelectSorted(p, ms...)
|
2020-01-17 03:21:44 -08:00
|
|
|
}
|
|
|
|
// Sorting Head series is slow, and unneeded when only the
|
|
|
|
// Head is being queried. Sorting blocks is a noop.
|
2020-02-06 07:58:38 -08:00
|
|
|
return q.blocks[0].Select(p, ms...)
|
2020-01-17 03:21:44 -08:00
|
|
|
}
|
|
|
|
|
2020-02-06 07:58:38 -08:00
|
|
|
func (q *querier) SelectSorted(p *storage.SelectParams, ms ...*labels.Matcher) (storage.SeriesSet, storage.Warnings, error) {
|
2019-11-15 06:45:29 -08:00
|
|
|
if len(q.blocks) == 0 {
|
2020-02-06 07:58:38 -08:00
|
|
|
return storage.EmptySeriesSet(), nil, nil
|
2016-12-20 04:10:37 -08:00
|
|
|
}
|
2020-02-06 07:58:38 -08:00
|
|
|
ss := make([]storage.SeriesSet, len(q.blocks))
|
|
|
|
var ws storage.Warnings
|
2019-11-15 06:45:29 -08:00
|
|
|
for i, b := range q.blocks {
|
2020-02-06 07:58:38 -08:00
|
|
|
s, w, err := b.SelectSorted(p, ms...)
|
|
|
|
ws = append(ws, w...)
|
2019-11-15 06:45:29 -08:00
|
|
|
if err != nil {
|
2020-02-06 07:58:38 -08:00
|
|
|
return nil, ws, err
|
2019-11-15 06:45:29 -08:00
|
|
|
}
|
|
|
|
ss[i] = s
|
2016-12-20 04:10:37 -08:00
|
|
|
}
|
2017-11-13 03:16:58 -08:00
|
|
|
|
2020-02-06 07:58:38 -08:00
|
|
|
return NewMergedSeriesSet(ss), ws, nil
|
2016-12-20 04:10:37 -08:00
|
|
|
}
|
|
|
|
|
2017-01-06 03:37:28 -08:00
|
|
|
func (q *querier) Close() error {
|
2019-03-19 06:31:57 -07:00
|
|
|
var merr tsdb_errors.MultiError
|
2016-12-28 02:41:44 -08:00
|
|
|
|
|
|
|
for _, bq := range q.blocks {
|
|
|
|
merr.Add(bq.Close())
|
|
|
|
}
|
|
|
|
return merr.Err()
|
2016-12-14 09:38:46 -08:00
|
|
|
}
|
|
|
|
|
2019-02-14 05:29:41 -08:00
|
|
|
// verticalQuerier aggregates querying results from time blocks within
|
|
|
|
// a single partition. The block time ranges can be overlapping.
|
|
|
|
type verticalQuerier struct {
|
|
|
|
querier
|
|
|
|
}
|
|
|
|
|
2020-02-06 07:58:38 -08:00
|
|
|
func (q *verticalQuerier) Select(p *storage.SelectParams, ms ...*labels.Matcher) (storage.SeriesSet, storage.Warnings, error) {
|
|
|
|
return q.sel(p, q.blocks, ms)
|
2019-02-14 05:29:41 -08:00
|
|
|
}
|
|
|
|
|
2020-02-06 07:58:38 -08:00
|
|
|
func (q *verticalQuerier) SelectSorted(p *storage.SelectParams, ms ...*labels.Matcher) (storage.SeriesSet, storage.Warnings, error) {
|
|
|
|
return q.sel(p, q.blocks, ms)
|
2020-01-17 03:21:44 -08:00
|
|
|
}
|
|
|
|
|
2020-02-06 07:58:38 -08:00
|
|
|
func (q *verticalQuerier) sel(p *storage.SelectParams, qs []storage.Querier, ms []*labels.Matcher) (storage.SeriesSet, storage.Warnings, error) {
|
2019-02-14 05:29:41 -08:00
|
|
|
if len(qs) == 0 {
|
2020-02-06 07:58:38 -08:00
|
|
|
return storage.EmptySeriesSet(), nil, nil
|
2019-02-14 05:29:41 -08:00
|
|
|
}
|
|
|
|
if len(qs) == 1 {
|
2020-02-06 07:58:38 -08:00
|
|
|
return qs[0].SelectSorted(p, ms...)
|
2019-02-14 05:29:41 -08:00
|
|
|
}
|
|
|
|
l := len(qs) / 2
|
|
|
|
|
2020-02-06 07:58:38 -08:00
|
|
|
var ws storage.Warnings
|
|
|
|
a, w, err := q.sel(p, qs[:l], ms)
|
|
|
|
ws = append(ws, w...)
|
2019-02-14 05:29:41 -08:00
|
|
|
if err != nil {
|
2020-02-06 07:58:38 -08:00
|
|
|
return nil, ws, err
|
2019-02-14 05:29:41 -08:00
|
|
|
}
|
2020-02-06 07:58:38 -08:00
|
|
|
b, w, err := q.sel(p, qs[l:], ms)
|
|
|
|
ws = append(ws, w...)
|
2019-02-14 05:29:41 -08:00
|
|
|
if err != nil {
|
2020-02-06 07:58:38 -08:00
|
|
|
return nil, ws, err
|
2019-02-14 05:29:41 -08:00
|
|
|
}
|
2020-02-06 07:58:38 -08:00
|
|
|
return newMergedVerticalSeriesSet(a, b), ws, nil
|
2019-02-14 05:29:41 -08:00
|
|
|
}
|
|
|
|
|
2018-01-09 07:40:31 -08:00
|
|
|
// NewBlockQuerier returns a querier against the reader.
|
2020-02-06 07:58:38 -08:00
|
|
|
func NewBlockQuerier(b BlockReader, mint, maxt int64) (storage.Querier, error) {
|
2017-10-09 06:21:46 -07:00
|
|
|
indexr, err := b.Index()
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrapf(err, "open index reader")
|
2017-08-25 01:32:54 -07:00
|
|
|
}
|
2017-10-09 06:21:46 -07:00
|
|
|
chunkr, err := b.Chunks()
|
|
|
|
if err != nil {
|
2017-10-23 11:30:03 -07:00
|
|
|
indexr.Close()
|
2017-10-09 06:21:46 -07:00
|
|
|
return nil, errors.Wrapf(err, "open chunk reader")
|
|
|
|
}
|
|
|
|
tombsr, err := b.Tombstones()
|
|
|
|
if err != nil {
|
2017-10-23 11:30:03 -07:00
|
|
|
indexr.Close()
|
|
|
|
chunkr.Close()
|
2017-10-09 06:21:46 -07:00
|
|
|
return nil, errors.Wrapf(err, "open tombstone reader")
|
|
|
|
}
|
|
|
|
return &blockQuerier{
|
|
|
|
mint: mint,
|
|
|
|
maxt: maxt,
|
|
|
|
index: indexr,
|
|
|
|
chunks: chunkr,
|
|
|
|
tombstones: tombsr,
|
|
|
|
}, nil
|
2017-08-25 01:32:54 -07:00
|
|
|
}
|
|
|
|
|
2016-12-14 09:38:46 -08:00
|
|
|
// blockQuerier provides querying access to a single block database.
|
|
|
|
type blockQuerier struct {
|
2017-05-16 07:18:28 -07:00
|
|
|
index IndexReader
|
|
|
|
chunks ChunkReader
|
2019-09-19 02:15:41 -07:00
|
|
|
tombstones tombstones.Reader
|
2016-12-14 09:38:46 -08:00
|
|
|
|
2019-04-30 00:17:07 -07:00
|
|
|
closed bool
|
|
|
|
|
2016-12-14 09:38:46 -08:00
|
|
|
mint, maxt int64
|
|
|
|
}
|
|
|
|
|
2020-02-06 07:58:38 -08:00
|
|
|
func (q *blockQuerier) Select(p *storage.SelectParams, ms ...*labels.Matcher) (storage.SeriesSet, storage.Warnings, error) {
|
2017-11-13 04:57:10 -08:00
|
|
|
base, err := LookupChunkSeries(q.index, q.tombstones, ms...)
|
2017-11-13 03:16:58 -08:00
|
|
|
if err != nil {
|
2020-02-06 07:58:38 -08:00
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
mint := q.mint
|
|
|
|
maxt := q.maxt
|
|
|
|
if p != nil {
|
|
|
|
mint = p.Start
|
|
|
|
maxt = p.End
|
2017-11-13 03:16:58 -08:00
|
|
|
}
|
2017-01-05 06:13:01 -08:00
|
|
|
return &blockSeriesSet{
|
2017-03-07 02:29:20 -08:00
|
|
|
set: &populatedChunkSeries{
|
2017-11-13 04:57:10 -08:00
|
|
|
set: base,
|
2017-03-07 02:29:20 -08:00
|
|
|
chunks: q.chunks,
|
2020-02-06 07:58:38 -08:00
|
|
|
mint: mint,
|
|
|
|
maxt: maxt,
|
2017-03-07 02:29:20 -08:00
|
|
|
},
|
2017-04-13 12:06:14 -07:00
|
|
|
|
2020-02-06 07:58:38 -08:00
|
|
|
mint: mint,
|
|
|
|
maxt: maxt,
|
|
|
|
}, nil, nil
|
2016-12-14 09:38:46 -08:00
|
|
|
}
|
|
|
|
|
2020-02-06 07:58:38 -08:00
|
|
|
func (q *blockQuerier) SelectSorted(p *storage.SelectParams, ms ...*labels.Matcher) (storage.SeriesSet, storage.Warnings, error) {
|
2020-01-17 03:21:44 -08:00
|
|
|
base, err := LookupChunkSeriesSorted(q.index, q.tombstones, ms...)
|
|
|
|
if err != nil {
|
2020-02-06 07:58:38 -08:00
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
mint := q.mint
|
|
|
|
maxt := q.maxt
|
|
|
|
if p != nil {
|
|
|
|
mint = p.Start
|
|
|
|
maxt = p.End
|
2020-01-17 03:21:44 -08:00
|
|
|
}
|
|
|
|
return &blockSeriesSet{
|
|
|
|
set: &populatedChunkSeries{
|
|
|
|
set: base,
|
|
|
|
chunks: q.chunks,
|
2020-02-06 07:58:38 -08:00
|
|
|
mint: mint,
|
|
|
|
maxt: maxt,
|
2020-01-17 03:21:44 -08:00
|
|
|
},
|
|
|
|
|
2020-02-06 07:58:38 -08:00
|
|
|
mint: mint,
|
|
|
|
maxt: maxt,
|
|
|
|
}, nil, nil
|
2017-05-13 08:43:25 -07:00
|
|
|
}
|
|
|
|
|
2020-02-06 07:58:38 -08:00
|
|
|
func (q *blockQuerier) LabelValues(name string) ([]string, storage.Warnings, error) {
|
|
|
|
res, err := q.index.LabelValues(name)
|
|
|
|
return res, nil, err
|
2018-11-16 10:02:24 -08:00
|
|
|
}
|
|
|
|
|
2020-02-06 07:58:38 -08:00
|
|
|
func (q *blockQuerier) LabelNames() ([]string, storage.Warnings, error) {
|
|
|
|
res, err := q.index.LabelNames()
|
|
|
|
return res, nil, err
|
2017-05-13 08:43:25 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
func (q *blockQuerier) Close() error {
|
2019-04-30 00:17:07 -07:00
|
|
|
if q.closed {
|
|
|
|
return errors.New("block querier already closed")
|
|
|
|
}
|
2017-10-09 06:21:46 -07:00
|
|
|
|
2019-04-30 00:17:07 -07:00
|
|
|
var merr tsdb_errors.MultiError
|
2017-10-09 06:21:46 -07:00
|
|
|
merr.Add(q.index.Close())
|
|
|
|
merr.Add(q.chunks.Close())
|
|
|
|
merr.Add(q.tombstones.Close())
|
2019-04-30 00:17:07 -07:00
|
|
|
q.closed = true
|
2017-10-09 06:21:46 -07:00
|
|
|
return merr.Err()
|
2017-05-13 08:43:25 -07:00
|
|
|
}
|
|
|
|
|
2019-05-27 04:24:46 -07:00
|
|
|
// Bitmap used by func isRegexMetaCharacter to check whether a character needs to be escaped.
|
|
|
|
var regexMetaCharacterBytes [16]byte
|
|
|
|
|
|
|
|
// isRegexMetaCharacter reports whether byte b needs to be escaped.
|
|
|
|
func isRegexMetaCharacter(b byte) bool {
|
|
|
|
return b < utf8.RuneSelf && regexMetaCharacterBytes[b%16]&(1<<(b/16)) != 0
|
|
|
|
}
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
for _, b := range []byte(`.+*?()|[]{}^$`) {
|
|
|
|
regexMetaCharacterBytes[b%16] |= 1 << (b / 16)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func findSetMatches(pattern string) []string {
|
|
|
|
// Return empty matches if the wrapper from Prometheus is missing.
|
|
|
|
if len(pattern) < 6 || pattern[:4] != "^(?:" || pattern[len(pattern)-2:] != ")$" {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
escaped := false
|
2019-08-13 01:34:14 -07:00
|
|
|
sets := []*strings.Builder{{}}
|
2019-05-27 04:24:46 -07:00
|
|
|
for i := 4; i < len(pattern)-2; i++ {
|
|
|
|
if escaped {
|
|
|
|
switch {
|
|
|
|
case isRegexMetaCharacter(pattern[i]):
|
|
|
|
sets[len(sets)-1].WriteByte(pattern[i])
|
|
|
|
case pattern[i] == '\\':
|
|
|
|
sets[len(sets)-1].WriteByte('\\')
|
|
|
|
default:
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
escaped = false
|
|
|
|
} else {
|
|
|
|
switch {
|
|
|
|
case isRegexMetaCharacter(pattern[i]):
|
|
|
|
if pattern[i] == '|' {
|
|
|
|
sets = append(sets, &strings.Builder{})
|
|
|
|
} else {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
case pattern[i] == '\\':
|
|
|
|
escaped = true
|
|
|
|
default:
|
|
|
|
sets[len(sets)-1].WriteByte(pattern[i])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
matches := make([]string, 0, len(sets))
|
|
|
|
for _, s := range sets {
|
|
|
|
if s.Len() > 0 {
|
|
|
|
matches = append(matches, s.String())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return matches
|
|
|
|
}
|
|
|
|
|
2017-11-13 04:57:10 -08:00
|
|
|
// PostingsForMatchers assembles a single postings iterator against the index reader
|
2020-01-17 03:21:44 -08:00
|
|
|
// based on the given matchers. The resulting postings are not ordered by series.
|
2019-11-18 11:53:33 -08:00
|
|
|
func PostingsForMatchers(ix IndexReader, ms ...*labels.Matcher) (index.Postings, error) {
|
Be smarter in how we look at matchers. (#572)
* Add unittests for PostingsForMatcher.
* Selector methods are all stateless, don't need a reference.
* Be smarter in how we look at matchers.
Look at all matchers to see if a label can be empty.
Optimise Not handling, so i!="2" is a simple lookup
rather than an inverse postings list.
All all the Withouts together, rather than
having to subtract each from all postings.
Change the pre-expand the postings logic to always do it before doing a
Without only. Don't do that if it's already a list.
The initial goal here was that the oft-seen pattern
i=~"something.+",i!="foo",i!="bar" becomes more efficient.
benchmark old ns/op new ns/op delta
BenchmarkHeadPostingForMatchers/n="1"-4 5888 6160 +4.62%
BenchmarkHeadPostingForMatchers/n="1",j="foo"-4 7190 6640 -7.65%
BenchmarkHeadPostingForMatchers/j="foo",n="1"-4 6038 5923 -1.90%
BenchmarkHeadPostingForMatchers/n="1",j!="foo"-4 6030884 4850525 -19.57%
BenchmarkHeadPostingForMatchers/i=~".*"-4 887377940 230329137 -74.04%
BenchmarkHeadPostingForMatchers/i=~".+"-4 490316101 319931758 -34.75%
BenchmarkHeadPostingForMatchers/i=~""-4 594961991 130279313 -78.10%
BenchmarkHeadPostingForMatchers/i!=""-4 537542388 318751015 -40.70%
BenchmarkHeadPostingForMatchers/n="1",i=~".*",j="foo"-4 10460243 8565195 -18.12%
BenchmarkHeadPostingForMatchers/n="1",i=~".*",i!="2",j="foo"-4 44964267 8561546 -80.96%
BenchmarkHeadPostingForMatchers/n="1",i!="",j="foo"-4 42244885 29137737 -31.03%
BenchmarkHeadPostingForMatchers/n="1",i=~".+",j="foo"-4 35285834 32774584 -7.12%
BenchmarkHeadPostingForMatchers/n="1",i=~"1.+",j="foo"-4 8951047 8379024 -6.39%
BenchmarkHeadPostingForMatchers/n="1",i=~".+",i!="2",j="foo"-4 63813335 30672688 -51.93%
BenchmarkHeadPostingForMatchers/n="1",i=~".+",i!~"2.*",j="foo"-4 45381112 44924397 -1.01%
Signed-off-by: Brian Brazil <brian.brazil@robustperception.io>
2019-04-09 03:59:45 -07:00
|
|
|
var its, notIts []index.Postings
|
|
|
|
// See which label must be non-empty.
|
2019-09-13 08:10:35 -07:00
|
|
|
// Optimization for case like {l=~".", l!="1"}.
|
Be smarter in how we look at matchers. (#572)
* Add unittests for PostingsForMatcher.
* Selector methods are all stateless, don't need a reference.
* Be smarter in how we look at matchers.
Look at all matchers to see if a label can be empty.
Optimise Not handling, so i!="2" is a simple lookup
rather than an inverse postings list.
All all the Withouts together, rather than
having to subtract each from all postings.
Change the pre-expand the postings logic to always do it before doing a
Without only. Don't do that if it's already a list.
The initial goal here was that the oft-seen pattern
i=~"something.+",i!="foo",i!="bar" becomes more efficient.
benchmark old ns/op new ns/op delta
BenchmarkHeadPostingForMatchers/n="1"-4 5888 6160 +4.62%
BenchmarkHeadPostingForMatchers/n="1",j="foo"-4 7190 6640 -7.65%
BenchmarkHeadPostingForMatchers/j="foo",n="1"-4 6038 5923 -1.90%
BenchmarkHeadPostingForMatchers/n="1",j!="foo"-4 6030884 4850525 -19.57%
BenchmarkHeadPostingForMatchers/i=~".*"-4 887377940 230329137 -74.04%
BenchmarkHeadPostingForMatchers/i=~".+"-4 490316101 319931758 -34.75%
BenchmarkHeadPostingForMatchers/i=~""-4 594961991 130279313 -78.10%
BenchmarkHeadPostingForMatchers/i!=""-4 537542388 318751015 -40.70%
BenchmarkHeadPostingForMatchers/n="1",i=~".*",j="foo"-4 10460243 8565195 -18.12%
BenchmarkHeadPostingForMatchers/n="1",i=~".*",i!="2",j="foo"-4 44964267 8561546 -80.96%
BenchmarkHeadPostingForMatchers/n="1",i!="",j="foo"-4 42244885 29137737 -31.03%
BenchmarkHeadPostingForMatchers/n="1",i=~".+",j="foo"-4 35285834 32774584 -7.12%
BenchmarkHeadPostingForMatchers/n="1",i=~"1.+",j="foo"-4 8951047 8379024 -6.39%
BenchmarkHeadPostingForMatchers/n="1",i=~".+",i!="2",j="foo"-4 63813335 30672688 -51.93%
BenchmarkHeadPostingForMatchers/n="1",i=~".+",i!~"2.*",j="foo"-4 45381112 44924397 -1.01%
Signed-off-by: Brian Brazil <brian.brazil@robustperception.io>
2019-04-09 03:59:45 -07:00
|
|
|
labelMustBeSet := make(map[string]bool, len(ms))
|
|
|
|
for _, m := range ms {
|
|
|
|
if !m.Matches("") {
|
2019-11-18 11:53:33 -08:00
|
|
|
labelMustBeSet[m.Name] = true
|
Be smarter in how we look at matchers. (#572)
* Add unittests for PostingsForMatcher.
* Selector methods are all stateless, don't need a reference.
* Be smarter in how we look at matchers.
Look at all matchers to see if a label can be empty.
Optimise Not handling, so i!="2" is a simple lookup
rather than an inverse postings list.
All all the Withouts together, rather than
having to subtract each from all postings.
Change the pre-expand the postings logic to always do it before doing a
Without only. Don't do that if it's already a list.
The initial goal here was that the oft-seen pattern
i=~"something.+",i!="foo",i!="bar" becomes more efficient.
benchmark old ns/op new ns/op delta
BenchmarkHeadPostingForMatchers/n="1"-4 5888 6160 +4.62%
BenchmarkHeadPostingForMatchers/n="1",j="foo"-4 7190 6640 -7.65%
BenchmarkHeadPostingForMatchers/j="foo",n="1"-4 6038 5923 -1.90%
BenchmarkHeadPostingForMatchers/n="1",j!="foo"-4 6030884 4850525 -19.57%
BenchmarkHeadPostingForMatchers/i=~".*"-4 887377940 230329137 -74.04%
BenchmarkHeadPostingForMatchers/i=~".+"-4 490316101 319931758 -34.75%
BenchmarkHeadPostingForMatchers/i=~""-4 594961991 130279313 -78.10%
BenchmarkHeadPostingForMatchers/i!=""-4 537542388 318751015 -40.70%
BenchmarkHeadPostingForMatchers/n="1",i=~".*",j="foo"-4 10460243 8565195 -18.12%
BenchmarkHeadPostingForMatchers/n="1",i=~".*",i!="2",j="foo"-4 44964267 8561546 -80.96%
BenchmarkHeadPostingForMatchers/n="1",i!="",j="foo"-4 42244885 29137737 -31.03%
BenchmarkHeadPostingForMatchers/n="1",i=~".+",j="foo"-4 35285834 32774584 -7.12%
BenchmarkHeadPostingForMatchers/n="1",i=~"1.+",j="foo"-4 8951047 8379024 -6.39%
BenchmarkHeadPostingForMatchers/n="1",i=~".+",i!="2",j="foo"-4 63813335 30672688 -51.93%
BenchmarkHeadPostingForMatchers/n="1",i=~".+",i!~"2.*",j="foo"-4 45381112 44924397 -1.01%
Signed-off-by: Brian Brazil <brian.brazil@robustperception.io>
2019-04-09 03:59:45 -07:00
|
|
|
}
|
|
|
|
}
|
2017-11-30 06:34:49 -08:00
|
|
|
|
2017-05-13 08:43:25 -07:00
|
|
|
for _, m := range ms {
|
2019-11-18 11:53:33 -08:00
|
|
|
if labelMustBeSet[m.Name] {
|
Be smarter in how we look at matchers. (#572)
* Add unittests for PostingsForMatcher.
* Selector methods are all stateless, don't need a reference.
* Be smarter in how we look at matchers.
Look at all matchers to see if a label can be empty.
Optimise Not handling, so i!="2" is a simple lookup
rather than an inverse postings list.
All all the Withouts together, rather than
having to subtract each from all postings.
Change the pre-expand the postings logic to always do it before doing a
Without only. Don't do that if it's already a list.
The initial goal here was that the oft-seen pattern
i=~"something.+",i!="foo",i!="bar" becomes more efficient.
benchmark old ns/op new ns/op delta
BenchmarkHeadPostingForMatchers/n="1"-4 5888 6160 +4.62%
BenchmarkHeadPostingForMatchers/n="1",j="foo"-4 7190 6640 -7.65%
BenchmarkHeadPostingForMatchers/j="foo",n="1"-4 6038 5923 -1.90%
BenchmarkHeadPostingForMatchers/n="1",j!="foo"-4 6030884 4850525 -19.57%
BenchmarkHeadPostingForMatchers/i=~".*"-4 887377940 230329137 -74.04%
BenchmarkHeadPostingForMatchers/i=~".+"-4 490316101 319931758 -34.75%
BenchmarkHeadPostingForMatchers/i=~""-4 594961991 130279313 -78.10%
BenchmarkHeadPostingForMatchers/i!=""-4 537542388 318751015 -40.70%
BenchmarkHeadPostingForMatchers/n="1",i=~".*",j="foo"-4 10460243 8565195 -18.12%
BenchmarkHeadPostingForMatchers/n="1",i=~".*",i!="2",j="foo"-4 44964267 8561546 -80.96%
BenchmarkHeadPostingForMatchers/n="1",i!="",j="foo"-4 42244885 29137737 -31.03%
BenchmarkHeadPostingForMatchers/n="1",i=~".+",j="foo"-4 35285834 32774584 -7.12%
BenchmarkHeadPostingForMatchers/n="1",i=~"1.+",j="foo"-4 8951047 8379024 -6.39%
BenchmarkHeadPostingForMatchers/n="1",i=~".+",i!="2",j="foo"-4 63813335 30672688 -51.93%
BenchmarkHeadPostingForMatchers/n="1",i=~".+",i!~"2.*",j="foo"-4 45381112 44924397 -1.01%
Signed-off-by: Brian Brazil <brian.brazil@robustperception.io>
2019-04-09 03:59:45 -07:00
|
|
|
// If this matcher must be non-empty, we can be smarter.
|
2019-09-13 08:10:35 -07:00
|
|
|
matchesEmpty := m.Matches("")
|
2019-11-18 11:53:33 -08:00
|
|
|
isNot := m.Type == labels.MatchNotEqual || m.Type == labels.MatchNotRegexp
|
Be smarter in how we look at matchers. (#572)
* Add unittests for PostingsForMatcher.
* Selector methods are all stateless, don't need a reference.
* Be smarter in how we look at matchers.
Look at all matchers to see if a label can be empty.
Optimise Not handling, so i!="2" is a simple lookup
rather than an inverse postings list.
All all the Withouts together, rather than
having to subtract each from all postings.
Change the pre-expand the postings logic to always do it before doing a
Without only. Don't do that if it's already a list.
The initial goal here was that the oft-seen pattern
i=~"something.+",i!="foo",i!="bar" becomes more efficient.
benchmark old ns/op new ns/op delta
BenchmarkHeadPostingForMatchers/n="1"-4 5888 6160 +4.62%
BenchmarkHeadPostingForMatchers/n="1",j="foo"-4 7190 6640 -7.65%
BenchmarkHeadPostingForMatchers/j="foo",n="1"-4 6038 5923 -1.90%
BenchmarkHeadPostingForMatchers/n="1",j!="foo"-4 6030884 4850525 -19.57%
BenchmarkHeadPostingForMatchers/i=~".*"-4 887377940 230329137 -74.04%
BenchmarkHeadPostingForMatchers/i=~".+"-4 490316101 319931758 -34.75%
BenchmarkHeadPostingForMatchers/i=~""-4 594961991 130279313 -78.10%
BenchmarkHeadPostingForMatchers/i!=""-4 537542388 318751015 -40.70%
BenchmarkHeadPostingForMatchers/n="1",i=~".*",j="foo"-4 10460243 8565195 -18.12%
BenchmarkHeadPostingForMatchers/n="1",i=~".*",i!="2",j="foo"-4 44964267 8561546 -80.96%
BenchmarkHeadPostingForMatchers/n="1",i!="",j="foo"-4 42244885 29137737 -31.03%
BenchmarkHeadPostingForMatchers/n="1",i=~".+",j="foo"-4 35285834 32774584 -7.12%
BenchmarkHeadPostingForMatchers/n="1",i=~"1.+",j="foo"-4 8951047 8379024 -6.39%
BenchmarkHeadPostingForMatchers/n="1",i=~".+",i!="2",j="foo"-4 63813335 30672688 -51.93%
BenchmarkHeadPostingForMatchers/n="1",i=~".+",i!~"2.*",j="foo"-4 45381112 44924397 -1.01%
Signed-off-by: Brian Brazil <brian.brazil@robustperception.io>
2019-04-09 03:59:45 -07:00
|
|
|
if isNot && matchesEmpty { // l!="foo"
|
|
|
|
// If the label can't be empty and is a Not and the inner matcher
|
|
|
|
// doesn't match empty, then subtract it out at the end.
|
2019-11-18 11:53:33 -08:00
|
|
|
inverse, err := m.Inverse()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
it, err := postingsForMatcher(ix, inverse)
|
Be smarter in how we look at matchers. (#572)
* Add unittests for PostingsForMatcher.
* Selector methods are all stateless, don't need a reference.
* Be smarter in how we look at matchers.
Look at all matchers to see if a label can be empty.
Optimise Not handling, so i!="2" is a simple lookup
rather than an inverse postings list.
All all the Withouts together, rather than
having to subtract each from all postings.
Change the pre-expand the postings logic to always do it before doing a
Without only. Don't do that if it's already a list.
The initial goal here was that the oft-seen pattern
i=~"something.+",i!="foo",i!="bar" becomes more efficient.
benchmark old ns/op new ns/op delta
BenchmarkHeadPostingForMatchers/n="1"-4 5888 6160 +4.62%
BenchmarkHeadPostingForMatchers/n="1",j="foo"-4 7190 6640 -7.65%
BenchmarkHeadPostingForMatchers/j="foo",n="1"-4 6038 5923 -1.90%
BenchmarkHeadPostingForMatchers/n="1",j!="foo"-4 6030884 4850525 -19.57%
BenchmarkHeadPostingForMatchers/i=~".*"-4 887377940 230329137 -74.04%
BenchmarkHeadPostingForMatchers/i=~".+"-4 490316101 319931758 -34.75%
BenchmarkHeadPostingForMatchers/i=~""-4 594961991 130279313 -78.10%
BenchmarkHeadPostingForMatchers/i!=""-4 537542388 318751015 -40.70%
BenchmarkHeadPostingForMatchers/n="1",i=~".*",j="foo"-4 10460243 8565195 -18.12%
BenchmarkHeadPostingForMatchers/n="1",i=~".*",i!="2",j="foo"-4 44964267 8561546 -80.96%
BenchmarkHeadPostingForMatchers/n="1",i!="",j="foo"-4 42244885 29137737 -31.03%
BenchmarkHeadPostingForMatchers/n="1",i=~".+",j="foo"-4 35285834 32774584 -7.12%
BenchmarkHeadPostingForMatchers/n="1",i=~"1.+",j="foo"-4 8951047 8379024 -6.39%
BenchmarkHeadPostingForMatchers/n="1",i=~".+",i!="2",j="foo"-4 63813335 30672688 -51.93%
BenchmarkHeadPostingForMatchers/n="1",i=~".+",i!~"2.*",j="foo"-4 45381112 44924397 -1.01%
Signed-off-by: Brian Brazil <brian.brazil@robustperception.io>
2019-04-09 03:59:45 -07:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
notIts = append(notIts, it)
|
|
|
|
} else if isNot && !matchesEmpty { // l!=""
|
|
|
|
// If the label can't be empty and is a Not, but the inner matcher can
|
|
|
|
// be empty we need to use inversePostingsForMatcher.
|
2019-11-18 11:53:33 -08:00
|
|
|
inverse, err := m.Inverse()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
it, err := inversePostingsForMatcher(ix, inverse)
|
Be smarter in how we look at matchers. (#572)
* Add unittests for PostingsForMatcher.
* Selector methods are all stateless, don't need a reference.
* Be smarter in how we look at matchers.
Look at all matchers to see if a label can be empty.
Optimise Not handling, so i!="2" is a simple lookup
rather than an inverse postings list.
All all the Withouts together, rather than
having to subtract each from all postings.
Change the pre-expand the postings logic to always do it before doing a
Without only. Don't do that if it's already a list.
The initial goal here was that the oft-seen pattern
i=~"something.+",i!="foo",i!="bar" becomes more efficient.
benchmark old ns/op new ns/op delta
BenchmarkHeadPostingForMatchers/n="1"-4 5888 6160 +4.62%
BenchmarkHeadPostingForMatchers/n="1",j="foo"-4 7190 6640 -7.65%
BenchmarkHeadPostingForMatchers/j="foo",n="1"-4 6038 5923 -1.90%
BenchmarkHeadPostingForMatchers/n="1",j!="foo"-4 6030884 4850525 -19.57%
BenchmarkHeadPostingForMatchers/i=~".*"-4 887377940 230329137 -74.04%
BenchmarkHeadPostingForMatchers/i=~".+"-4 490316101 319931758 -34.75%
BenchmarkHeadPostingForMatchers/i=~""-4 594961991 130279313 -78.10%
BenchmarkHeadPostingForMatchers/i!=""-4 537542388 318751015 -40.70%
BenchmarkHeadPostingForMatchers/n="1",i=~".*",j="foo"-4 10460243 8565195 -18.12%
BenchmarkHeadPostingForMatchers/n="1",i=~".*",i!="2",j="foo"-4 44964267 8561546 -80.96%
BenchmarkHeadPostingForMatchers/n="1",i!="",j="foo"-4 42244885 29137737 -31.03%
BenchmarkHeadPostingForMatchers/n="1",i=~".+",j="foo"-4 35285834 32774584 -7.12%
BenchmarkHeadPostingForMatchers/n="1",i=~"1.+",j="foo"-4 8951047 8379024 -6.39%
BenchmarkHeadPostingForMatchers/n="1",i=~".+",i!="2",j="foo"-4 63813335 30672688 -51.93%
BenchmarkHeadPostingForMatchers/n="1",i=~".+",i!~"2.*",j="foo"-4 45381112 44924397 -1.01%
Signed-off-by: Brian Brazil <brian.brazil@robustperception.io>
2019-04-09 03:59:45 -07:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
its = append(its, it)
|
|
|
|
} else { // l="a"
|
|
|
|
// Non-Not matcher, use normal postingsForMatcher.
|
|
|
|
it, err := postingsForMatcher(ix, m)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
its = append(its, it)
|
|
|
|
}
|
|
|
|
} else { // l=""
|
|
|
|
// If the matchers for a labelname selects an empty value, it selects all
|
|
|
|
// the series which don't have the label name set too. See:
|
|
|
|
// https://github.com/prometheus/prometheus/issues/3575 and
|
|
|
|
// https://github.com/prometheus/prometheus/pull/3578#issuecomment-351653555
|
|
|
|
it, err := inversePostingsForMatcher(ix, m)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
notIts = append(notIts, it)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If there's nothing to subtract from, add in everything and remove the notIts later.
|
|
|
|
if len(its) == 0 && len(notIts) != 0 {
|
Reduce memory used by postings offset table.
Rather than keeping the offset of each postings list, instead
keep the nth offset of the offset of the posting list. As postings
list offsets have always been sorted, we can then get to the closest
entry before the one we want an iterate forwards.
I haven't done much tuning on the 32 number, it was chosen to try
not to read through more than a 4k page of data.
Switch to a bulk interface for fetching postings. Use it to avoid having
to re-read parts of the posting offset table when querying lots of it.
For a index with what BenchmarkHeadPostingForMatchers uses RAM
for r.postings drops from 3.79MB to 80.19kB or about 48x.
Bytes allocated go down by 30%, and suprisingly CPU usage drops by
4-6% for typical queries too.
benchmark old ns/op new ns/op delta
BenchmarkPostingsForMatchers/Block/n="1"-4 35231 36673 +4.09%
BenchmarkPostingsForMatchers/Block/n="1",j="foo"-4 563380 540627 -4.04%
BenchmarkPostingsForMatchers/Block/j="foo",n="1"-4 536782 534186 -0.48%
BenchmarkPostingsForMatchers/Block/n="1",j!="foo"-4 533990 541550 +1.42%
BenchmarkPostingsForMatchers/Block/i=~".*"-4 113374598 117969608 +4.05%
BenchmarkPostingsForMatchers/Block/i=~".+"-4 146329884 139651442 -4.56%
BenchmarkPostingsForMatchers/Block/i=~""-4 50346510 44961127 -10.70%
BenchmarkPostingsForMatchers/Block/i!=""-4 41261550 35356165 -14.31%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",j="foo"-4 112544418 116904010 +3.87%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",i!="2",j="foo"-4 112487086 116864918 +3.89%
BenchmarkPostingsForMatchers/Block/n="1",i!=""-4 41094758 35457904 -13.72%
BenchmarkPostingsForMatchers/Block/n="1",i!="",j="foo"-4 41906372 36151473 -13.73%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",j="foo"-4 147262414 140424800 -4.64%
BenchmarkPostingsForMatchers/Block/n="1",i=~"1.+",j="foo"-4 28615629 27872072 -2.60%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!="2",j="foo"-4 147117177 140462403 -4.52%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!~"2.*",j="foo"-4 175096826 167902298 -4.11%
benchmark old allocs new allocs delta
BenchmarkPostingsForMatchers/Block/n="1"-4 4 6 +50.00%
BenchmarkPostingsForMatchers/Block/n="1",j="foo"-4 7 11 +57.14%
BenchmarkPostingsForMatchers/Block/j="foo",n="1"-4 7 11 +57.14%
BenchmarkPostingsForMatchers/Block/n="1",j!="foo"-4 15 17 +13.33%
BenchmarkPostingsForMatchers/Block/i=~".*"-4 100010 100012 +0.00%
BenchmarkPostingsForMatchers/Block/i=~".+"-4 200069 200040 -0.01%
BenchmarkPostingsForMatchers/Block/i=~""-4 200072 200045 -0.01%
BenchmarkPostingsForMatchers/Block/i!=""-4 200070 200041 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",j="foo"-4 100013 100017 +0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",i!="2",j="foo"-4 100017 100023 +0.01%
BenchmarkPostingsForMatchers/Block/n="1",i!=""-4 200073 200046 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i!="",j="foo"-4 200075 200050 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",j="foo"-4 200074 200049 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i=~"1.+",j="foo"-4 111165 111150 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!="2",j="foo"-4 200078 200055 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!~"2.*",j="foo"-4 311282 311238 -0.01%
benchmark old bytes new bytes delta
BenchmarkPostingsForMatchers/Block/n="1"-4 264 296 +12.12%
BenchmarkPostingsForMatchers/Block/n="1",j="foo"-4 360 424 +17.78%
BenchmarkPostingsForMatchers/Block/j="foo",n="1"-4 360 424 +17.78%
BenchmarkPostingsForMatchers/Block/n="1",j!="foo"-4 520 552 +6.15%
BenchmarkPostingsForMatchers/Block/i=~".*"-4 1600461 1600482 +0.00%
BenchmarkPostingsForMatchers/Block/i=~".+"-4 24900801 17259077 -30.69%
BenchmarkPostingsForMatchers/Block/i=~""-4 24900836 17259151 -30.69%
BenchmarkPostingsForMatchers/Block/i!=""-4 24900760 17259048 -30.69%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",j="foo"-4 1600557 1600621 +0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",i!="2",j="foo"-4 1600717 1600813 +0.01%
BenchmarkPostingsForMatchers/Block/n="1",i!=""-4 24900856 17259176 -30.69%
BenchmarkPostingsForMatchers/Block/n="1",i!="",j="foo"-4 24900952 17259304 -30.69%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",j="foo"-4 24900993 17259333 -30.69%
BenchmarkPostingsForMatchers/Block/n="1",i=~"1.+",j="foo"-4 3788311 3142630 -17.04%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!="2",j="foo"-4 24901137 17259509 -30.69%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!~"2.*",j="foo"-4 28693086 20405680 -28.88%
Signed-off-by: Brian Brazil <brian.brazil@robustperception.io>
2019-12-05 10:27:40 -08:00
|
|
|
k, v := index.AllPostingsKey()
|
|
|
|
allPostings, err := ix.Postings(k, v)
|
2017-11-13 03:16:58 -08:00
|
|
|
if err != nil {
|
2017-12-17 10:08:21 -08:00
|
|
|
return nil, err
|
2017-11-13 03:16:58 -08:00
|
|
|
}
|
Be smarter in how we look at matchers. (#572)
* Add unittests for PostingsForMatcher.
* Selector methods are all stateless, don't need a reference.
* Be smarter in how we look at matchers.
Look at all matchers to see if a label can be empty.
Optimise Not handling, so i!="2" is a simple lookup
rather than an inverse postings list.
All all the Withouts together, rather than
having to subtract each from all postings.
Change the pre-expand the postings logic to always do it before doing a
Without only. Don't do that if it's already a list.
The initial goal here was that the oft-seen pattern
i=~"something.+",i!="foo",i!="bar" becomes more efficient.
benchmark old ns/op new ns/op delta
BenchmarkHeadPostingForMatchers/n="1"-4 5888 6160 +4.62%
BenchmarkHeadPostingForMatchers/n="1",j="foo"-4 7190 6640 -7.65%
BenchmarkHeadPostingForMatchers/j="foo",n="1"-4 6038 5923 -1.90%
BenchmarkHeadPostingForMatchers/n="1",j!="foo"-4 6030884 4850525 -19.57%
BenchmarkHeadPostingForMatchers/i=~".*"-4 887377940 230329137 -74.04%
BenchmarkHeadPostingForMatchers/i=~".+"-4 490316101 319931758 -34.75%
BenchmarkHeadPostingForMatchers/i=~""-4 594961991 130279313 -78.10%
BenchmarkHeadPostingForMatchers/i!=""-4 537542388 318751015 -40.70%
BenchmarkHeadPostingForMatchers/n="1",i=~".*",j="foo"-4 10460243 8565195 -18.12%
BenchmarkHeadPostingForMatchers/n="1",i=~".*",i!="2",j="foo"-4 44964267 8561546 -80.96%
BenchmarkHeadPostingForMatchers/n="1",i!="",j="foo"-4 42244885 29137737 -31.03%
BenchmarkHeadPostingForMatchers/n="1",i=~".+",j="foo"-4 35285834 32774584 -7.12%
BenchmarkHeadPostingForMatchers/n="1",i=~"1.+",j="foo"-4 8951047 8379024 -6.39%
BenchmarkHeadPostingForMatchers/n="1",i=~".+",i!="2",j="foo"-4 63813335 30672688 -51.93%
BenchmarkHeadPostingForMatchers/n="1",i=~".+",i!~"2.*",j="foo"-4 45381112 44924397 -1.01%
Signed-off-by: Brian Brazil <brian.brazil@robustperception.io>
2019-04-09 03:59:45 -07:00
|
|
|
its = append(its, allPostings)
|
2017-05-13 08:43:25 -07:00
|
|
|
}
|
Be smarter in how we look at matchers. (#572)
* Add unittests for PostingsForMatcher.
* Selector methods are all stateless, don't need a reference.
* Be smarter in how we look at matchers.
Look at all matchers to see if a label can be empty.
Optimise Not handling, so i!="2" is a simple lookup
rather than an inverse postings list.
All all the Withouts together, rather than
having to subtract each from all postings.
Change the pre-expand the postings logic to always do it before doing a
Without only. Don't do that if it's already a list.
The initial goal here was that the oft-seen pattern
i=~"something.+",i!="foo",i!="bar" becomes more efficient.
benchmark old ns/op new ns/op delta
BenchmarkHeadPostingForMatchers/n="1"-4 5888 6160 +4.62%
BenchmarkHeadPostingForMatchers/n="1",j="foo"-4 7190 6640 -7.65%
BenchmarkHeadPostingForMatchers/j="foo",n="1"-4 6038 5923 -1.90%
BenchmarkHeadPostingForMatchers/n="1",j!="foo"-4 6030884 4850525 -19.57%
BenchmarkHeadPostingForMatchers/i=~".*"-4 887377940 230329137 -74.04%
BenchmarkHeadPostingForMatchers/i=~".+"-4 490316101 319931758 -34.75%
BenchmarkHeadPostingForMatchers/i=~""-4 594961991 130279313 -78.10%
BenchmarkHeadPostingForMatchers/i!=""-4 537542388 318751015 -40.70%
BenchmarkHeadPostingForMatchers/n="1",i=~".*",j="foo"-4 10460243 8565195 -18.12%
BenchmarkHeadPostingForMatchers/n="1",i=~".*",i!="2",j="foo"-4 44964267 8561546 -80.96%
BenchmarkHeadPostingForMatchers/n="1",i!="",j="foo"-4 42244885 29137737 -31.03%
BenchmarkHeadPostingForMatchers/n="1",i=~".+",j="foo"-4 35285834 32774584 -7.12%
BenchmarkHeadPostingForMatchers/n="1",i=~"1.+",j="foo"-4 8951047 8379024 -6.39%
BenchmarkHeadPostingForMatchers/n="1",i=~".+",i!="2",j="foo"-4 63813335 30672688 -51.93%
BenchmarkHeadPostingForMatchers/n="1",i=~".+",i!~"2.*",j="foo"-4 45381112 44924397 -1.01%
Signed-off-by: Brian Brazil <brian.brazil@robustperception.io>
2019-04-09 03:59:45 -07:00
|
|
|
|
|
|
|
it := index.Intersect(its...)
|
|
|
|
|
|
|
|
for _, n := range notIts {
|
|
|
|
it = index.Without(it, n)
|
|
|
|
}
|
|
|
|
|
2020-01-17 03:21:44 -08:00
|
|
|
return it, nil
|
2017-05-13 08:43:25 -07:00
|
|
|
}
|
|
|
|
|
2019-11-18 11:53:33 -08:00
|
|
|
func postingsForMatcher(ix IndexReader, m *labels.Matcher) (index.Postings, error) {
|
Be smarter in how we look at matchers. (#572)
* Add unittests for PostingsForMatcher.
* Selector methods are all stateless, don't need a reference.
* Be smarter in how we look at matchers.
Look at all matchers to see if a label can be empty.
Optimise Not handling, so i!="2" is a simple lookup
rather than an inverse postings list.
All all the Withouts together, rather than
having to subtract each from all postings.
Change the pre-expand the postings logic to always do it before doing a
Without only. Don't do that if it's already a list.
The initial goal here was that the oft-seen pattern
i=~"something.+",i!="foo",i!="bar" becomes more efficient.
benchmark old ns/op new ns/op delta
BenchmarkHeadPostingForMatchers/n="1"-4 5888 6160 +4.62%
BenchmarkHeadPostingForMatchers/n="1",j="foo"-4 7190 6640 -7.65%
BenchmarkHeadPostingForMatchers/j="foo",n="1"-4 6038 5923 -1.90%
BenchmarkHeadPostingForMatchers/n="1",j!="foo"-4 6030884 4850525 -19.57%
BenchmarkHeadPostingForMatchers/i=~".*"-4 887377940 230329137 -74.04%
BenchmarkHeadPostingForMatchers/i=~".+"-4 490316101 319931758 -34.75%
BenchmarkHeadPostingForMatchers/i=~""-4 594961991 130279313 -78.10%
BenchmarkHeadPostingForMatchers/i!=""-4 537542388 318751015 -40.70%
BenchmarkHeadPostingForMatchers/n="1",i=~".*",j="foo"-4 10460243 8565195 -18.12%
BenchmarkHeadPostingForMatchers/n="1",i=~".*",i!="2",j="foo"-4 44964267 8561546 -80.96%
BenchmarkHeadPostingForMatchers/n="1",i!="",j="foo"-4 42244885 29137737 -31.03%
BenchmarkHeadPostingForMatchers/n="1",i=~".+",j="foo"-4 35285834 32774584 -7.12%
BenchmarkHeadPostingForMatchers/n="1",i=~"1.+",j="foo"-4 8951047 8379024 -6.39%
BenchmarkHeadPostingForMatchers/n="1",i=~".+",i!="2",j="foo"-4 63813335 30672688 -51.93%
BenchmarkHeadPostingForMatchers/n="1",i=~".+",i!~"2.*",j="foo"-4 45381112 44924397 -1.01%
Signed-off-by: Brian Brazil <brian.brazil@robustperception.io>
2019-04-09 03:59:45 -07:00
|
|
|
// This method will not return postings for missing labels.
|
2017-12-17 10:08:21 -08:00
|
|
|
|
2017-04-05 05:14:30 -07:00
|
|
|
// Fast-path for equal matching.
|
2019-11-18 11:53:33 -08:00
|
|
|
if m.Type == labels.MatchEqual {
|
|
|
|
return ix.Postings(m.Name, m.Value)
|
2017-04-05 05:14:30 -07:00
|
|
|
}
|
|
|
|
|
2019-05-27 04:24:46 -07:00
|
|
|
// Fast-path for set matching.
|
2019-11-18 11:53:33 -08:00
|
|
|
if m.Type == labels.MatchRegexp {
|
2020-02-05 02:53:12 -08:00
|
|
|
setMatches := findSetMatches(m.GetRegexString())
|
2019-05-27 04:24:46 -07:00
|
|
|
if len(setMatches) > 0 {
|
Reduce memory used by postings offset table.
Rather than keeping the offset of each postings list, instead
keep the nth offset of the offset of the posting list. As postings
list offsets have always been sorted, we can then get to the closest
entry before the one we want an iterate forwards.
I haven't done much tuning on the 32 number, it was chosen to try
not to read through more than a 4k page of data.
Switch to a bulk interface for fetching postings. Use it to avoid having
to re-read parts of the posting offset table when querying lots of it.
For a index with what BenchmarkHeadPostingForMatchers uses RAM
for r.postings drops from 3.79MB to 80.19kB or about 48x.
Bytes allocated go down by 30%, and suprisingly CPU usage drops by
4-6% for typical queries too.
benchmark old ns/op new ns/op delta
BenchmarkPostingsForMatchers/Block/n="1"-4 35231 36673 +4.09%
BenchmarkPostingsForMatchers/Block/n="1",j="foo"-4 563380 540627 -4.04%
BenchmarkPostingsForMatchers/Block/j="foo",n="1"-4 536782 534186 -0.48%
BenchmarkPostingsForMatchers/Block/n="1",j!="foo"-4 533990 541550 +1.42%
BenchmarkPostingsForMatchers/Block/i=~".*"-4 113374598 117969608 +4.05%
BenchmarkPostingsForMatchers/Block/i=~".+"-4 146329884 139651442 -4.56%
BenchmarkPostingsForMatchers/Block/i=~""-4 50346510 44961127 -10.70%
BenchmarkPostingsForMatchers/Block/i!=""-4 41261550 35356165 -14.31%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",j="foo"-4 112544418 116904010 +3.87%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",i!="2",j="foo"-4 112487086 116864918 +3.89%
BenchmarkPostingsForMatchers/Block/n="1",i!=""-4 41094758 35457904 -13.72%
BenchmarkPostingsForMatchers/Block/n="1",i!="",j="foo"-4 41906372 36151473 -13.73%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",j="foo"-4 147262414 140424800 -4.64%
BenchmarkPostingsForMatchers/Block/n="1",i=~"1.+",j="foo"-4 28615629 27872072 -2.60%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!="2",j="foo"-4 147117177 140462403 -4.52%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!~"2.*",j="foo"-4 175096826 167902298 -4.11%
benchmark old allocs new allocs delta
BenchmarkPostingsForMatchers/Block/n="1"-4 4 6 +50.00%
BenchmarkPostingsForMatchers/Block/n="1",j="foo"-4 7 11 +57.14%
BenchmarkPostingsForMatchers/Block/j="foo",n="1"-4 7 11 +57.14%
BenchmarkPostingsForMatchers/Block/n="1",j!="foo"-4 15 17 +13.33%
BenchmarkPostingsForMatchers/Block/i=~".*"-4 100010 100012 +0.00%
BenchmarkPostingsForMatchers/Block/i=~".+"-4 200069 200040 -0.01%
BenchmarkPostingsForMatchers/Block/i=~""-4 200072 200045 -0.01%
BenchmarkPostingsForMatchers/Block/i!=""-4 200070 200041 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",j="foo"-4 100013 100017 +0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",i!="2",j="foo"-4 100017 100023 +0.01%
BenchmarkPostingsForMatchers/Block/n="1",i!=""-4 200073 200046 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i!="",j="foo"-4 200075 200050 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",j="foo"-4 200074 200049 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i=~"1.+",j="foo"-4 111165 111150 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!="2",j="foo"-4 200078 200055 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!~"2.*",j="foo"-4 311282 311238 -0.01%
benchmark old bytes new bytes delta
BenchmarkPostingsForMatchers/Block/n="1"-4 264 296 +12.12%
BenchmarkPostingsForMatchers/Block/n="1",j="foo"-4 360 424 +17.78%
BenchmarkPostingsForMatchers/Block/j="foo",n="1"-4 360 424 +17.78%
BenchmarkPostingsForMatchers/Block/n="1",j!="foo"-4 520 552 +6.15%
BenchmarkPostingsForMatchers/Block/i=~".*"-4 1600461 1600482 +0.00%
BenchmarkPostingsForMatchers/Block/i=~".+"-4 24900801 17259077 -30.69%
BenchmarkPostingsForMatchers/Block/i=~""-4 24900836 17259151 -30.69%
BenchmarkPostingsForMatchers/Block/i!=""-4 24900760 17259048 -30.69%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",j="foo"-4 1600557 1600621 +0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",i!="2",j="foo"-4 1600717 1600813 +0.01%
BenchmarkPostingsForMatchers/Block/n="1",i!=""-4 24900856 17259176 -30.69%
BenchmarkPostingsForMatchers/Block/n="1",i!="",j="foo"-4 24900952 17259304 -30.69%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",j="foo"-4 24900993 17259333 -30.69%
BenchmarkPostingsForMatchers/Block/n="1",i=~"1.+",j="foo"-4 3788311 3142630 -17.04%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!="2",j="foo"-4 24901137 17259509 -30.69%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!~"2.*",j="foo"-4 28693086 20405680 -28.88%
Signed-off-by: Brian Brazil <brian.brazil@robustperception.io>
2019-12-05 10:27:40 -08:00
|
|
|
sort.Strings(setMatches)
|
|
|
|
return ix.Postings(m.Name, setMatches...)
|
2019-05-27 04:24:46 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Replace StringTuples with []string
Benchmarks show slight cpu/allocs improvements.
benchmark old ns/op new ns/op delta
BenchmarkPostingsForMatchers/Head/n="1"-4 269978625 235305110 -12.84%
BenchmarkPostingsForMatchers/Head/n="1",j="foo"-4 129739974 121646193 -6.24%
BenchmarkPostingsForMatchers/Head/j="foo",n="1"-4 123826274 122056253 -1.43%
BenchmarkPostingsForMatchers/Head/n="1",j!="foo"-4 126962188 130038235 +2.42%
BenchmarkPostingsForMatchers/Head/i=~".*"-4 6423653989 5991126455 -6.73%
BenchmarkPostingsForMatchers/Head/i=~".+"-4 6934647521 7033370634 +1.42%
BenchmarkPostingsForMatchers/Head/i=~""-4 1177781285 1121497736 -4.78%
BenchmarkPostingsForMatchers/Head/i!=""-4 7033680256 7246094991 +3.02%
BenchmarkPostingsForMatchers/Head/n="1",i=~".*",j="foo"-4 293702332 287440212 -2.13%
BenchmarkPostingsForMatchers/Head/n="1",i=~".*",i!="2",j="foo"-4 307628268 307039964 -0.19%
BenchmarkPostingsForMatchers/Head/n="1",i!=""-4 512247746 480003862 -6.29%
BenchmarkPostingsForMatchers/Head/n="1",i!="",j="foo"-4 361199794 367066917 +1.62%
BenchmarkPostingsForMatchers/Head/n="1",i=~".+",j="foo"-4 478863761 476037784 -0.59%
BenchmarkPostingsForMatchers/Head/n="1",i=~"1.+",j="foo"-4 103394659 102902098 -0.48%
BenchmarkPostingsForMatchers/Head/n="1",i=~".+",i!="2",j="foo"-4 482552781 475453903 -1.47%
BenchmarkPostingsForMatchers/Head/n="1",i=~".+",i!~"2.*",j="foo"-4 559257389 589297047 +5.37%
BenchmarkPostingsForMatchers/Block/n="1"-4 36492 37012 +1.42%
BenchmarkPostingsForMatchers/Block/n="1",j="foo"-4 557788 611903 +9.70%
BenchmarkPostingsForMatchers/Block/j="foo",n="1"-4 554443 573814 +3.49%
BenchmarkPostingsForMatchers/Block/n="1",j!="foo"-4 553227 553826 +0.11%
BenchmarkPostingsForMatchers/Block/i=~".*"-4 113855090 111707221 -1.89%
BenchmarkPostingsForMatchers/Block/i=~".+"-4 133994674 136520728 +1.89%
BenchmarkPostingsForMatchers/Block/i=~""-4 38138091 36299898 -4.82%
BenchmarkPostingsForMatchers/Block/i!=""-4 28861213 27396723 -5.07%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",j="foo"-4 112699941 110853868 -1.64%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",i!="2",j="foo"-4 113198026 111389742 -1.60%
BenchmarkPostingsForMatchers/Block/n="1",i!=""-4 28994069 27363804 -5.62%
BenchmarkPostingsForMatchers/Block/n="1",i!="",j="foo"-4 29709406 28589223 -3.77%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",j="foo"-4 134695119 135736971 +0.77%
BenchmarkPostingsForMatchers/Block/n="1",i=~"1.+",j="foo"-4 26783286 25826928 -3.57%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!="2",j="foo"-4 134733254 134116739 -0.46%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!~"2.*",j="foo"-4 160713937 158802768 -1.19%
benchmark old allocs new allocs delta
BenchmarkPostingsForMatchers/Head/n="1"-4 36 36 +0.00%
BenchmarkPostingsForMatchers/Head/n="1",j="foo"-4 38 38 +0.00%
BenchmarkPostingsForMatchers/Head/j="foo",n="1"-4 38 38 +0.00%
BenchmarkPostingsForMatchers/Head/n="1",j!="foo"-4 42 40 -4.76%
BenchmarkPostingsForMatchers/Head/i=~".*"-4 61 59 -3.28%
BenchmarkPostingsForMatchers/Head/i=~".+"-4 100088 100087 -0.00%
BenchmarkPostingsForMatchers/Head/i=~""-4 100053 100051 -0.00%
BenchmarkPostingsForMatchers/Head/i!=""-4 100087 100085 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i=~".*",j="foo"-4 44 42 -4.55%
BenchmarkPostingsForMatchers/Head/n="1",i=~".*",i!="2",j="foo"-4 50 48 -4.00%
BenchmarkPostingsForMatchers/Head/n="1",i!=""-4 100076 100074 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i!="",j="foo"-4 100077 100075 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i=~".+",j="foo"-4 100077 100074 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i=~"1.+",j="foo"-4 11167 11165 -0.02%
BenchmarkPostingsForMatchers/Head/n="1",i=~".+",i!="2",j="foo"-4 100082 100080 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i=~".+",i!~"2.*",j="foo"-4 111265 111261 -0.00%
BenchmarkPostingsForMatchers/Block/n="1"-4 6 6 +0.00%
BenchmarkPostingsForMatchers/Block/n="1",j="foo"-4 11 11 +0.00%
BenchmarkPostingsForMatchers/Block/j="foo",n="1"-4 11 11 +0.00%
BenchmarkPostingsForMatchers/Block/n="1",j!="foo"-4 15 13 -13.33%
BenchmarkPostingsForMatchers/Block/i=~".*"-4 12 10 -16.67%
BenchmarkPostingsForMatchers/Block/i=~".+"-4 100040 100038 -0.00%
BenchmarkPostingsForMatchers/Block/i=~""-4 100045 100043 -0.00%
BenchmarkPostingsForMatchers/Block/i!=""-4 100041 100039 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",j="foo"-4 17 15 -11.76%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",i!="2",j="foo"-4 23 21 -8.70%
BenchmarkPostingsForMatchers/Block/n="1",i!=""-4 100046 100044 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i!="",j="foo"-4 100050 100048 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",j="foo"-4 100049 100047 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~"1.+",j="foo"-4 11150 11148 -0.02%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!="2",j="foo"-4 100055 100053 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!~"2.*",j="foo"-4 111238 111234 -0.00%
benchmark old bytes new bytes delta
BenchmarkPostingsForMatchers/Head/n="1"-4 10887816 10887817 +0.00%
BenchmarkPostingsForMatchers/Head/n="1",j="foo"-4 5456648 5456648 +0.00%
BenchmarkPostingsForMatchers/Head/j="foo",n="1"-4 5456648 5456648 +0.00%
BenchmarkPostingsForMatchers/Head/n="1",j!="foo"-4 5456792 5456712 -0.00%
BenchmarkPostingsForMatchers/Head/i=~".*"-4 258254408 258254328 -0.00%
BenchmarkPostingsForMatchers/Head/i=~".+"-4 273912888 273912904 +0.00%
BenchmarkPostingsForMatchers/Head/i=~""-4 17266680 17266600 -0.00%
BenchmarkPostingsForMatchers/Head/i!=""-4 273912416 273912336 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i=~".*",j="foo"-4 7062578 7062498 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i=~".*",i!="2",j="foo"-4 7062770 7062690 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i!=""-4 28152346 28152266 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i!="",j="foo"-4 22721178 22721098 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i=~".+",j="foo"-4 22721336 22721224 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i=~"1.+",j="foo"-4 3623804 3623733 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i=~".+",i!="2",j="foo"-4 22721480 22721400 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i=~".+",i!~"2.*",j="foo"-4 24816652 24816444 -0.00%
BenchmarkPostingsForMatchers/Block/n="1"-4 296 296 +0.00%
BenchmarkPostingsForMatchers/Block/n="1",j="foo"-4 424 424 +0.00%
BenchmarkPostingsForMatchers/Block/j="foo",n="1"-4 424 424 +0.00%
BenchmarkPostingsForMatchers/Block/n="1",j!="foo"-4 1544 1464 -5.18%
BenchmarkPostingsForMatchers/Block/i=~".*"-4 1606114 1606045 -0.00%
BenchmarkPostingsForMatchers/Block/i=~".+"-4 17264709 17264629 -0.00%
BenchmarkPostingsForMatchers/Block/i=~""-4 17264780 17264696 -0.00%
BenchmarkPostingsForMatchers/Block/i!=""-4 17264680 17264600 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",j="foo"-4 1606253 1606165 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",i!="2",j="foo"-4 1606445 1606348 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i!=""-4 17264808 17264728 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i!="",j="foo"-4 17264936 17264856 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",j="foo"-4 17264965 17264885 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~"1.+",j="foo"-4 3148262 3148182 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!="2",j="foo"-4 17265141 17265061 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!~"2.*",j="foo"-4 20416944 20416784 -0.00%
Signed-off-by: Brian Brazil <brian.brazil@robustperception.io>
2020-01-01 03:38:01 -08:00
|
|
|
vals, err := ix.LabelValues(m.Name)
|
2016-12-14 09:38:46 -08:00
|
|
|
if err != nil {
|
2017-11-13 03:16:58 -08:00
|
|
|
return nil, err
|
2016-12-14 09:38:46 -08:00
|
|
|
}
|
2017-05-13 08:43:25 -07:00
|
|
|
|
2016-12-14 09:38:46 -08:00
|
|
|
var res []string
|
Replace StringTuples with []string
Benchmarks show slight cpu/allocs improvements.
benchmark old ns/op new ns/op delta
BenchmarkPostingsForMatchers/Head/n="1"-4 269978625 235305110 -12.84%
BenchmarkPostingsForMatchers/Head/n="1",j="foo"-4 129739974 121646193 -6.24%
BenchmarkPostingsForMatchers/Head/j="foo",n="1"-4 123826274 122056253 -1.43%
BenchmarkPostingsForMatchers/Head/n="1",j!="foo"-4 126962188 130038235 +2.42%
BenchmarkPostingsForMatchers/Head/i=~".*"-4 6423653989 5991126455 -6.73%
BenchmarkPostingsForMatchers/Head/i=~".+"-4 6934647521 7033370634 +1.42%
BenchmarkPostingsForMatchers/Head/i=~""-4 1177781285 1121497736 -4.78%
BenchmarkPostingsForMatchers/Head/i!=""-4 7033680256 7246094991 +3.02%
BenchmarkPostingsForMatchers/Head/n="1",i=~".*",j="foo"-4 293702332 287440212 -2.13%
BenchmarkPostingsForMatchers/Head/n="1",i=~".*",i!="2",j="foo"-4 307628268 307039964 -0.19%
BenchmarkPostingsForMatchers/Head/n="1",i!=""-4 512247746 480003862 -6.29%
BenchmarkPostingsForMatchers/Head/n="1",i!="",j="foo"-4 361199794 367066917 +1.62%
BenchmarkPostingsForMatchers/Head/n="1",i=~".+",j="foo"-4 478863761 476037784 -0.59%
BenchmarkPostingsForMatchers/Head/n="1",i=~"1.+",j="foo"-4 103394659 102902098 -0.48%
BenchmarkPostingsForMatchers/Head/n="1",i=~".+",i!="2",j="foo"-4 482552781 475453903 -1.47%
BenchmarkPostingsForMatchers/Head/n="1",i=~".+",i!~"2.*",j="foo"-4 559257389 589297047 +5.37%
BenchmarkPostingsForMatchers/Block/n="1"-4 36492 37012 +1.42%
BenchmarkPostingsForMatchers/Block/n="1",j="foo"-4 557788 611903 +9.70%
BenchmarkPostingsForMatchers/Block/j="foo",n="1"-4 554443 573814 +3.49%
BenchmarkPostingsForMatchers/Block/n="1",j!="foo"-4 553227 553826 +0.11%
BenchmarkPostingsForMatchers/Block/i=~".*"-4 113855090 111707221 -1.89%
BenchmarkPostingsForMatchers/Block/i=~".+"-4 133994674 136520728 +1.89%
BenchmarkPostingsForMatchers/Block/i=~""-4 38138091 36299898 -4.82%
BenchmarkPostingsForMatchers/Block/i!=""-4 28861213 27396723 -5.07%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",j="foo"-4 112699941 110853868 -1.64%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",i!="2",j="foo"-4 113198026 111389742 -1.60%
BenchmarkPostingsForMatchers/Block/n="1",i!=""-4 28994069 27363804 -5.62%
BenchmarkPostingsForMatchers/Block/n="1",i!="",j="foo"-4 29709406 28589223 -3.77%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",j="foo"-4 134695119 135736971 +0.77%
BenchmarkPostingsForMatchers/Block/n="1",i=~"1.+",j="foo"-4 26783286 25826928 -3.57%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!="2",j="foo"-4 134733254 134116739 -0.46%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!~"2.*",j="foo"-4 160713937 158802768 -1.19%
benchmark old allocs new allocs delta
BenchmarkPostingsForMatchers/Head/n="1"-4 36 36 +0.00%
BenchmarkPostingsForMatchers/Head/n="1",j="foo"-4 38 38 +0.00%
BenchmarkPostingsForMatchers/Head/j="foo",n="1"-4 38 38 +0.00%
BenchmarkPostingsForMatchers/Head/n="1",j!="foo"-4 42 40 -4.76%
BenchmarkPostingsForMatchers/Head/i=~".*"-4 61 59 -3.28%
BenchmarkPostingsForMatchers/Head/i=~".+"-4 100088 100087 -0.00%
BenchmarkPostingsForMatchers/Head/i=~""-4 100053 100051 -0.00%
BenchmarkPostingsForMatchers/Head/i!=""-4 100087 100085 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i=~".*",j="foo"-4 44 42 -4.55%
BenchmarkPostingsForMatchers/Head/n="1",i=~".*",i!="2",j="foo"-4 50 48 -4.00%
BenchmarkPostingsForMatchers/Head/n="1",i!=""-4 100076 100074 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i!="",j="foo"-4 100077 100075 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i=~".+",j="foo"-4 100077 100074 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i=~"1.+",j="foo"-4 11167 11165 -0.02%
BenchmarkPostingsForMatchers/Head/n="1",i=~".+",i!="2",j="foo"-4 100082 100080 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i=~".+",i!~"2.*",j="foo"-4 111265 111261 -0.00%
BenchmarkPostingsForMatchers/Block/n="1"-4 6 6 +0.00%
BenchmarkPostingsForMatchers/Block/n="1",j="foo"-4 11 11 +0.00%
BenchmarkPostingsForMatchers/Block/j="foo",n="1"-4 11 11 +0.00%
BenchmarkPostingsForMatchers/Block/n="1",j!="foo"-4 15 13 -13.33%
BenchmarkPostingsForMatchers/Block/i=~".*"-4 12 10 -16.67%
BenchmarkPostingsForMatchers/Block/i=~".+"-4 100040 100038 -0.00%
BenchmarkPostingsForMatchers/Block/i=~""-4 100045 100043 -0.00%
BenchmarkPostingsForMatchers/Block/i!=""-4 100041 100039 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",j="foo"-4 17 15 -11.76%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",i!="2",j="foo"-4 23 21 -8.70%
BenchmarkPostingsForMatchers/Block/n="1",i!=""-4 100046 100044 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i!="",j="foo"-4 100050 100048 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",j="foo"-4 100049 100047 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~"1.+",j="foo"-4 11150 11148 -0.02%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!="2",j="foo"-4 100055 100053 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!~"2.*",j="foo"-4 111238 111234 -0.00%
benchmark old bytes new bytes delta
BenchmarkPostingsForMatchers/Head/n="1"-4 10887816 10887817 +0.00%
BenchmarkPostingsForMatchers/Head/n="1",j="foo"-4 5456648 5456648 +0.00%
BenchmarkPostingsForMatchers/Head/j="foo",n="1"-4 5456648 5456648 +0.00%
BenchmarkPostingsForMatchers/Head/n="1",j!="foo"-4 5456792 5456712 -0.00%
BenchmarkPostingsForMatchers/Head/i=~".*"-4 258254408 258254328 -0.00%
BenchmarkPostingsForMatchers/Head/i=~".+"-4 273912888 273912904 +0.00%
BenchmarkPostingsForMatchers/Head/i=~""-4 17266680 17266600 -0.00%
BenchmarkPostingsForMatchers/Head/i!=""-4 273912416 273912336 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i=~".*",j="foo"-4 7062578 7062498 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i=~".*",i!="2",j="foo"-4 7062770 7062690 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i!=""-4 28152346 28152266 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i!="",j="foo"-4 22721178 22721098 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i=~".+",j="foo"-4 22721336 22721224 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i=~"1.+",j="foo"-4 3623804 3623733 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i=~".+",i!="2",j="foo"-4 22721480 22721400 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i=~".+",i!~"2.*",j="foo"-4 24816652 24816444 -0.00%
BenchmarkPostingsForMatchers/Block/n="1"-4 296 296 +0.00%
BenchmarkPostingsForMatchers/Block/n="1",j="foo"-4 424 424 +0.00%
BenchmarkPostingsForMatchers/Block/j="foo",n="1"-4 424 424 +0.00%
BenchmarkPostingsForMatchers/Block/n="1",j!="foo"-4 1544 1464 -5.18%
BenchmarkPostingsForMatchers/Block/i=~".*"-4 1606114 1606045 -0.00%
BenchmarkPostingsForMatchers/Block/i=~".+"-4 17264709 17264629 -0.00%
BenchmarkPostingsForMatchers/Block/i=~""-4 17264780 17264696 -0.00%
BenchmarkPostingsForMatchers/Block/i!=""-4 17264680 17264600 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",j="foo"-4 1606253 1606165 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",i!="2",j="foo"-4 1606445 1606348 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i!=""-4 17264808 17264728 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i!="",j="foo"-4 17264936 17264856 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",j="foo"-4 17264965 17264885 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~"1.+",j="foo"-4 3148262 3148182 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!="2",j="foo"-4 17265141 17265061 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!~"2.*",j="foo"-4 20416944 20416784 -0.00%
Signed-off-by: Brian Brazil <brian.brazil@robustperception.io>
2020-01-01 03:38:01 -08:00
|
|
|
for _, val := range vals {
|
2020-01-01 03:21:42 -08:00
|
|
|
if m.Matches(val) {
|
|
|
|
res = append(res, val)
|
2016-12-14 09:38:46 -08:00
|
|
|
}
|
|
|
|
}
|
2017-05-13 08:43:25 -07:00
|
|
|
|
2016-12-14 09:38:46 -08:00
|
|
|
if len(res) == 0 {
|
2017-11-30 06:34:49 -08:00
|
|
|
return index.EmptyPostings(), nil
|
2016-12-14 09:38:46 -08:00
|
|
|
}
|
|
|
|
|
Reduce memory used by postings offset table.
Rather than keeping the offset of each postings list, instead
keep the nth offset of the offset of the posting list. As postings
list offsets have always been sorted, we can then get to the closest
entry before the one we want an iterate forwards.
I haven't done much tuning on the 32 number, it was chosen to try
not to read through more than a 4k page of data.
Switch to a bulk interface for fetching postings. Use it to avoid having
to re-read parts of the posting offset table when querying lots of it.
For a index with what BenchmarkHeadPostingForMatchers uses RAM
for r.postings drops from 3.79MB to 80.19kB or about 48x.
Bytes allocated go down by 30%, and suprisingly CPU usage drops by
4-6% for typical queries too.
benchmark old ns/op new ns/op delta
BenchmarkPostingsForMatchers/Block/n="1"-4 35231 36673 +4.09%
BenchmarkPostingsForMatchers/Block/n="1",j="foo"-4 563380 540627 -4.04%
BenchmarkPostingsForMatchers/Block/j="foo",n="1"-4 536782 534186 -0.48%
BenchmarkPostingsForMatchers/Block/n="1",j!="foo"-4 533990 541550 +1.42%
BenchmarkPostingsForMatchers/Block/i=~".*"-4 113374598 117969608 +4.05%
BenchmarkPostingsForMatchers/Block/i=~".+"-4 146329884 139651442 -4.56%
BenchmarkPostingsForMatchers/Block/i=~""-4 50346510 44961127 -10.70%
BenchmarkPostingsForMatchers/Block/i!=""-4 41261550 35356165 -14.31%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",j="foo"-4 112544418 116904010 +3.87%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",i!="2",j="foo"-4 112487086 116864918 +3.89%
BenchmarkPostingsForMatchers/Block/n="1",i!=""-4 41094758 35457904 -13.72%
BenchmarkPostingsForMatchers/Block/n="1",i!="",j="foo"-4 41906372 36151473 -13.73%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",j="foo"-4 147262414 140424800 -4.64%
BenchmarkPostingsForMatchers/Block/n="1",i=~"1.+",j="foo"-4 28615629 27872072 -2.60%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!="2",j="foo"-4 147117177 140462403 -4.52%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!~"2.*",j="foo"-4 175096826 167902298 -4.11%
benchmark old allocs new allocs delta
BenchmarkPostingsForMatchers/Block/n="1"-4 4 6 +50.00%
BenchmarkPostingsForMatchers/Block/n="1",j="foo"-4 7 11 +57.14%
BenchmarkPostingsForMatchers/Block/j="foo",n="1"-4 7 11 +57.14%
BenchmarkPostingsForMatchers/Block/n="1",j!="foo"-4 15 17 +13.33%
BenchmarkPostingsForMatchers/Block/i=~".*"-4 100010 100012 +0.00%
BenchmarkPostingsForMatchers/Block/i=~".+"-4 200069 200040 -0.01%
BenchmarkPostingsForMatchers/Block/i=~""-4 200072 200045 -0.01%
BenchmarkPostingsForMatchers/Block/i!=""-4 200070 200041 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",j="foo"-4 100013 100017 +0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",i!="2",j="foo"-4 100017 100023 +0.01%
BenchmarkPostingsForMatchers/Block/n="1",i!=""-4 200073 200046 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i!="",j="foo"-4 200075 200050 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",j="foo"-4 200074 200049 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i=~"1.+",j="foo"-4 111165 111150 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!="2",j="foo"-4 200078 200055 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!~"2.*",j="foo"-4 311282 311238 -0.01%
benchmark old bytes new bytes delta
BenchmarkPostingsForMatchers/Block/n="1"-4 264 296 +12.12%
BenchmarkPostingsForMatchers/Block/n="1",j="foo"-4 360 424 +17.78%
BenchmarkPostingsForMatchers/Block/j="foo",n="1"-4 360 424 +17.78%
BenchmarkPostingsForMatchers/Block/n="1",j!="foo"-4 520 552 +6.15%
BenchmarkPostingsForMatchers/Block/i=~".*"-4 1600461 1600482 +0.00%
BenchmarkPostingsForMatchers/Block/i=~".+"-4 24900801 17259077 -30.69%
BenchmarkPostingsForMatchers/Block/i=~""-4 24900836 17259151 -30.69%
BenchmarkPostingsForMatchers/Block/i!=""-4 24900760 17259048 -30.69%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",j="foo"-4 1600557 1600621 +0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",i!="2",j="foo"-4 1600717 1600813 +0.01%
BenchmarkPostingsForMatchers/Block/n="1",i!=""-4 24900856 17259176 -30.69%
BenchmarkPostingsForMatchers/Block/n="1",i!="",j="foo"-4 24900952 17259304 -30.69%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",j="foo"-4 24900993 17259333 -30.69%
BenchmarkPostingsForMatchers/Block/n="1",i=~"1.+",j="foo"-4 3788311 3142630 -17.04%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!="2",j="foo"-4 24901137 17259509 -30.69%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!~"2.*",j="foo"-4 28693086 20405680 -28.88%
Signed-off-by: Brian Brazil <brian.brazil@robustperception.io>
2019-12-05 10:27:40 -08:00
|
|
|
return ix.Postings(m.Name, res...)
|
2016-12-14 09:38:46 -08:00
|
|
|
}
|
|
|
|
|
2019-09-13 08:10:35 -07:00
|
|
|
// inversePostingsForMatcher returns the postings for the series with the label name set but not matching the matcher.
|
2019-11-18 11:53:33 -08:00
|
|
|
func inversePostingsForMatcher(ix IndexReader, m *labels.Matcher) (index.Postings, error) {
|
Replace StringTuples with []string
Benchmarks show slight cpu/allocs improvements.
benchmark old ns/op new ns/op delta
BenchmarkPostingsForMatchers/Head/n="1"-4 269978625 235305110 -12.84%
BenchmarkPostingsForMatchers/Head/n="1",j="foo"-4 129739974 121646193 -6.24%
BenchmarkPostingsForMatchers/Head/j="foo",n="1"-4 123826274 122056253 -1.43%
BenchmarkPostingsForMatchers/Head/n="1",j!="foo"-4 126962188 130038235 +2.42%
BenchmarkPostingsForMatchers/Head/i=~".*"-4 6423653989 5991126455 -6.73%
BenchmarkPostingsForMatchers/Head/i=~".+"-4 6934647521 7033370634 +1.42%
BenchmarkPostingsForMatchers/Head/i=~""-4 1177781285 1121497736 -4.78%
BenchmarkPostingsForMatchers/Head/i!=""-4 7033680256 7246094991 +3.02%
BenchmarkPostingsForMatchers/Head/n="1",i=~".*",j="foo"-4 293702332 287440212 -2.13%
BenchmarkPostingsForMatchers/Head/n="1",i=~".*",i!="2",j="foo"-4 307628268 307039964 -0.19%
BenchmarkPostingsForMatchers/Head/n="1",i!=""-4 512247746 480003862 -6.29%
BenchmarkPostingsForMatchers/Head/n="1",i!="",j="foo"-4 361199794 367066917 +1.62%
BenchmarkPostingsForMatchers/Head/n="1",i=~".+",j="foo"-4 478863761 476037784 -0.59%
BenchmarkPostingsForMatchers/Head/n="1",i=~"1.+",j="foo"-4 103394659 102902098 -0.48%
BenchmarkPostingsForMatchers/Head/n="1",i=~".+",i!="2",j="foo"-4 482552781 475453903 -1.47%
BenchmarkPostingsForMatchers/Head/n="1",i=~".+",i!~"2.*",j="foo"-4 559257389 589297047 +5.37%
BenchmarkPostingsForMatchers/Block/n="1"-4 36492 37012 +1.42%
BenchmarkPostingsForMatchers/Block/n="1",j="foo"-4 557788 611903 +9.70%
BenchmarkPostingsForMatchers/Block/j="foo",n="1"-4 554443 573814 +3.49%
BenchmarkPostingsForMatchers/Block/n="1",j!="foo"-4 553227 553826 +0.11%
BenchmarkPostingsForMatchers/Block/i=~".*"-4 113855090 111707221 -1.89%
BenchmarkPostingsForMatchers/Block/i=~".+"-4 133994674 136520728 +1.89%
BenchmarkPostingsForMatchers/Block/i=~""-4 38138091 36299898 -4.82%
BenchmarkPostingsForMatchers/Block/i!=""-4 28861213 27396723 -5.07%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",j="foo"-4 112699941 110853868 -1.64%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",i!="2",j="foo"-4 113198026 111389742 -1.60%
BenchmarkPostingsForMatchers/Block/n="1",i!=""-4 28994069 27363804 -5.62%
BenchmarkPostingsForMatchers/Block/n="1",i!="",j="foo"-4 29709406 28589223 -3.77%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",j="foo"-4 134695119 135736971 +0.77%
BenchmarkPostingsForMatchers/Block/n="1",i=~"1.+",j="foo"-4 26783286 25826928 -3.57%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!="2",j="foo"-4 134733254 134116739 -0.46%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!~"2.*",j="foo"-4 160713937 158802768 -1.19%
benchmark old allocs new allocs delta
BenchmarkPostingsForMatchers/Head/n="1"-4 36 36 +0.00%
BenchmarkPostingsForMatchers/Head/n="1",j="foo"-4 38 38 +0.00%
BenchmarkPostingsForMatchers/Head/j="foo",n="1"-4 38 38 +0.00%
BenchmarkPostingsForMatchers/Head/n="1",j!="foo"-4 42 40 -4.76%
BenchmarkPostingsForMatchers/Head/i=~".*"-4 61 59 -3.28%
BenchmarkPostingsForMatchers/Head/i=~".+"-4 100088 100087 -0.00%
BenchmarkPostingsForMatchers/Head/i=~""-4 100053 100051 -0.00%
BenchmarkPostingsForMatchers/Head/i!=""-4 100087 100085 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i=~".*",j="foo"-4 44 42 -4.55%
BenchmarkPostingsForMatchers/Head/n="1",i=~".*",i!="2",j="foo"-4 50 48 -4.00%
BenchmarkPostingsForMatchers/Head/n="1",i!=""-4 100076 100074 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i!="",j="foo"-4 100077 100075 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i=~".+",j="foo"-4 100077 100074 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i=~"1.+",j="foo"-4 11167 11165 -0.02%
BenchmarkPostingsForMatchers/Head/n="1",i=~".+",i!="2",j="foo"-4 100082 100080 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i=~".+",i!~"2.*",j="foo"-4 111265 111261 -0.00%
BenchmarkPostingsForMatchers/Block/n="1"-4 6 6 +0.00%
BenchmarkPostingsForMatchers/Block/n="1",j="foo"-4 11 11 +0.00%
BenchmarkPostingsForMatchers/Block/j="foo",n="1"-4 11 11 +0.00%
BenchmarkPostingsForMatchers/Block/n="1",j!="foo"-4 15 13 -13.33%
BenchmarkPostingsForMatchers/Block/i=~".*"-4 12 10 -16.67%
BenchmarkPostingsForMatchers/Block/i=~".+"-4 100040 100038 -0.00%
BenchmarkPostingsForMatchers/Block/i=~""-4 100045 100043 -0.00%
BenchmarkPostingsForMatchers/Block/i!=""-4 100041 100039 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",j="foo"-4 17 15 -11.76%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",i!="2",j="foo"-4 23 21 -8.70%
BenchmarkPostingsForMatchers/Block/n="1",i!=""-4 100046 100044 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i!="",j="foo"-4 100050 100048 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",j="foo"-4 100049 100047 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~"1.+",j="foo"-4 11150 11148 -0.02%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!="2",j="foo"-4 100055 100053 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!~"2.*",j="foo"-4 111238 111234 -0.00%
benchmark old bytes new bytes delta
BenchmarkPostingsForMatchers/Head/n="1"-4 10887816 10887817 +0.00%
BenchmarkPostingsForMatchers/Head/n="1",j="foo"-4 5456648 5456648 +0.00%
BenchmarkPostingsForMatchers/Head/j="foo",n="1"-4 5456648 5456648 +0.00%
BenchmarkPostingsForMatchers/Head/n="1",j!="foo"-4 5456792 5456712 -0.00%
BenchmarkPostingsForMatchers/Head/i=~".*"-4 258254408 258254328 -0.00%
BenchmarkPostingsForMatchers/Head/i=~".+"-4 273912888 273912904 +0.00%
BenchmarkPostingsForMatchers/Head/i=~""-4 17266680 17266600 -0.00%
BenchmarkPostingsForMatchers/Head/i!=""-4 273912416 273912336 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i=~".*",j="foo"-4 7062578 7062498 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i=~".*",i!="2",j="foo"-4 7062770 7062690 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i!=""-4 28152346 28152266 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i!="",j="foo"-4 22721178 22721098 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i=~".+",j="foo"-4 22721336 22721224 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i=~"1.+",j="foo"-4 3623804 3623733 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i=~".+",i!="2",j="foo"-4 22721480 22721400 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i=~".+",i!~"2.*",j="foo"-4 24816652 24816444 -0.00%
BenchmarkPostingsForMatchers/Block/n="1"-4 296 296 +0.00%
BenchmarkPostingsForMatchers/Block/n="1",j="foo"-4 424 424 +0.00%
BenchmarkPostingsForMatchers/Block/j="foo",n="1"-4 424 424 +0.00%
BenchmarkPostingsForMatchers/Block/n="1",j!="foo"-4 1544 1464 -5.18%
BenchmarkPostingsForMatchers/Block/i=~".*"-4 1606114 1606045 -0.00%
BenchmarkPostingsForMatchers/Block/i=~".+"-4 17264709 17264629 -0.00%
BenchmarkPostingsForMatchers/Block/i=~""-4 17264780 17264696 -0.00%
BenchmarkPostingsForMatchers/Block/i!=""-4 17264680 17264600 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",j="foo"-4 1606253 1606165 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",i!="2",j="foo"-4 1606445 1606348 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i!=""-4 17264808 17264728 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i!="",j="foo"-4 17264936 17264856 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",j="foo"-4 17264965 17264885 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~"1.+",j="foo"-4 3148262 3148182 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!="2",j="foo"-4 17265141 17265061 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!~"2.*",j="foo"-4 20416944 20416784 -0.00%
Signed-off-by: Brian Brazil <brian.brazil@robustperception.io>
2020-01-01 03:38:01 -08:00
|
|
|
vals, err := ix.LabelValues(m.Name)
|
2017-12-17 10:08:21 -08:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
var res []string
|
Replace StringTuples with []string
Benchmarks show slight cpu/allocs improvements.
benchmark old ns/op new ns/op delta
BenchmarkPostingsForMatchers/Head/n="1"-4 269978625 235305110 -12.84%
BenchmarkPostingsForMatchers/Head/n="1",j="foo"-4 129739974 121646193 -6.24%
BenchmarkPostingsForMatchers/Head/j="foo",n="1"-4 123826274 122056253 -1.43%
BenchmarkPostingsForMatchers/Head/n="1",j!="foo"-4 126962188 130038235 +2.42%
BenchmarkPostingsForMatchers/Head/i=~".*"-4 6423653989 5991126455 -6.73%
BenchmarkPostingsForMatchers/Head/i=~".+"-4 6934647521 7033370634 +1.42%
BenchmarkPostingsForMatchers/Head/i=~""-4 1177781285 1121497736 -4.78%
BenchmarkPostingsForMatchers/Head/i!=""-4 7033680256 7246094991 +3.02%
BenchmarkPostingsForMatchers/Head/n="1",i=~".*",j="foo"-4 293702332 287440212 -2.13%
BenchmarkPostingsForMatchers/Head/n="1",i=~".*",i!="2",j="foo"-4 307628268 307039964 -0.19%
BenchmarkPostingsForMatchers/Head/n="1",i!=""-4 512247746 480003862 -6.29%
BenchmarkPostingsForMatchers/Head/n="1",i!="",j="foo"-4 361199794 367066917 +1.62%
BenchmarkPostingsForMatchers/Head/n="1",i=~".+",j="foo"-4 478863761 476037784 -0.59%
BenchmarkPostingsForMatchers/Head/n="1",i=~"1.+",j="foo"-4 103394659 102902098 -0.48%
BenchmarkPostingsForMatchers/Head/n="1",i=~".+",i!="2",j="foo"-4 482552781 475453903 -1.47%
BenchmarkPostingsForMatchers/Head/n="1",i=~".+",i!~"2.*",j="foo"-4 559257389 589297047 +5.37%
BenchmarkPostingsForMatchers/Block/n="1"-4 36492 37012 +1.42%
BenchmarkPostingsForMatchers/Block/n="1",j="foo"-4 557788 611903 +9.70%
BenchmarkPostingsForMatchers/Block/j="foo",n="1"-4 554443 573814 +3.49%
BenchmarkPostingsForMatchers/Block/n="1",j!="foo"-4 553227 553826 +0.11%
BenchmarkPostingsForMatchers/Block/i=~".*"-4 113855090 111707221 -1.89%
BenchmarkPostingsForMatchers/Block/i=~".+"-4 133994674 136520728 +1.89%
BenchmarkPostingsForMatchers/Block/i=~""-4 38138091 36299898 -4.82%
BenchmarkPostingsForMatchers/Block/i!=""-4 28861213 27396723 -5.07%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",j="foo"-4 112699941 110853868 -1.64%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",i!="2",j="foo"-4 113198026 111389742 -1.60%
BenchmarkPostingsForMatchers/Block/n="1",i!=""-4 28994069 27363804 -5.62%
BenchmarkPostingsForMatchers/Block/n="1",i!="",j="foo"-4 29709406 28589223 -3.77%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",j="foo"-4 134695119 135736971 +0.77%
BenchmarkPostingsForMatchers/Block/n="1",i=~"1.+",j="foo"-4 26783286 25826928 -3.57%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!="2",j="foo"-4 134733254 134116739 -0.46%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!~"2.*",j="foo"-4 160713937 158802768 -1.19%
benchmark old allocs new allocs delta
BenchmarkPostingsForMatchers/Head/n="1"-4 36 36 +0.00%
BenchmarkPostingsForMatchers/Head/n="1",j="foo"-4 38 38 +0.00%
BenchmarkPostingsForMatchers/Head/j="foo",n="1"-4 38 38 +0.00%
BenchmarkPostingsForMatchers/Head/n="1",j!="foo"-4 42 40 -4.76%
BenchmarkPostingsForMatchers/Head/i=~".*"-4 61 59 -3.28%
BenchmarkPostingsForMatchers/Head/i=~".+"-4 100088 100087 -0.00%
BenchmarkPostingsForMatchers/Head/i=~""-4 100053 100051 -0.00%
BenchmarkPostingsForMatchers/Head/i!=""-4 100087 100085 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i=~".*",j="foo"-4 44 42 -4.55%
BenchmarkPostingsForMatchers/Head/n="1",i=~".*",i!="2",j="foo"-4 50 48 -4.00%
BenchmarkPostingsForMatchers/Head/n="1",i!=""-4 100076 100074 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i!="",j="foo"-4 100077 100075 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i=~".+",j="foo"-4 100077 100074 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i=~"1.+",j="foo"-4 11167 11165 -0.02%
BenchmarkPostingsForMatchers/Head/n="1",i=~".+",i!="2",j="foo"-4 100082 100080 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i=~".+",i!~"2.*",j="foo"-4 111265 111261 -0.00%
BenchmarkPostingsForMatchers/Block/n="1"-4 6 6 +0.00%
BenchmarkPostingsForMatchers/Block/n="1",j="foo"-4 11 11 +0.00%
BenchmarkPostingsForMatchers/Block/j="foo",n="1"-4 11 11 +0.00%
BenchmarkPostingsForMatchers/Block/n="1",j!="foo"-4 15 13 -13.33%
BenchmarkPostingsForMatchers/Block/i=~".*"-4 12 10 -16.67%
BenchmarkPostingsForMatchers/Block/i=~".+"-4 100040 100038 -0.00%
BenchmarkPostingsForMatchers/Block/i=~""-4 100045 100043 -0.00%
BenchmarkPostingsForMatchers/Block/i!=""-4 100041 100039 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",j="foo"-4 17 15 -11.76%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",i!="2",j="foo"-4 23 21 -8.70%
BenchmarkPostingsForMatchers/Block/n="1",i!=""-4 100046 100044 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i!="",j="foo"-4 100050 100048 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",j="foo"-4 100049 100047 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~"1.+",j="foo"-4 11150 11148 -0.02%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!="2",j="foo"-4 100055 100053 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!~"2.*",j="foo"-4 111238 111234 -0.00%
benchmark old bytes new bytes delta
BenchmarkPostingsForMatchers/Head/n="1"-4 10887816 10887817 +0.00%
BenchmarkPostingsForMatchers/Head/n="1",j="foo"-4 5456648 5456648 +0.00%
BenchmarkPostingsForMatchers/Head/j="foo",n="1"-4 5456648 5456648 +0.00%
BenchmarkPostingsForMatchers/Head/n="1",j!="foo"-4 5456792 5456712 -0.00%
BenchmarkPostingsForMatchers/Head/i=~".*"-4 258254408 258254328 -0.00%
BenchmarkPostingsForMatchers/Head/i=~".+"-4 273912888 273912904 +0.00%
BenchmarkPostingsForMatchers/Head/i=~""-4 17266680 17266600 -0.00%
BenchmarkPostingsForMatchers/Head/i!=""-4 273912416 273912336 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i=~".*",j="foo"-4 7062578 7062498 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i=~".*",i!="2",j="foo"-4 7062770 7062690 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i!=""-4 28152346 28152266 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i!="",j="foo"-4 22721178 22721098 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i=~".+",j="foo"-4 22721336 22721224 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i=~"1.+",j="foo"-4 3623804 3623733 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i=~".+",i!="2",j="foo"-4 22721480 22721400 -0.00%
BenchmarkPostingsForMatchers/Head/n="1",i=~".+",i!~"2.*",j="foo"-4 24816652 24816444 -0.00%
BenchmarkPostingsForMatchers/Block/n="1"-4 296 296 +0.00%
BenchmarkPostingsForMatchers/Block/n="1",j="foo"-4 424 424 +0.00%
BenchmarkPostingsForMatchers/Block/j="foo",n="1"-4 424 424 +0.00%
BenchmarkPostingsForMatchers/Block/n="1",j!="foo"-4 1544 1464 -5.18%
BenchmarkPostingsForMatchers/Block/i=~".*"-4 1606114 1606045 -0.00%
BenchmarkPostingsForMatchers/Block/i=~".+"-4 17264709 17264629 -0.00%
BenchmarkPostingsForMatchers/Block/i=~""-4 17264780 17264696 -0.00%
BenchmarkPostingsForMatchers/Block/i!=""-4 17264680 17264600 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",j="foo"-4 1606253 1606165 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",i!="2",j="foo"-4 1606445 1606348 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i!=""-4 17264808 17264728 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i!="",j="foo"-4 17264936 17264856 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",j="foo"-4 17264965 17264885 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~"1.+",j="foo"-4 3148262 3148182 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!="2",j="foo"-4 17265141 17265061 -0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!~"2.*",j="foo"-4 20416944 20416784 -0.00%
Signed-off-by: Brian Brazil <brian.brazil@robustperception.io>
2020-01-01 03:38:01 -08:00
|
|
|
for _, val := range vals {
|
2020-01-01 03:21:42 -08:00
|
|
|
if !m.Matches(val) {
|
|
|
|
res = append(res, val)
|
2017-12-17 10:08:21 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Reduce memory used by postings offset table.
Rather than keeping the offset of each postings list, instead
keep the nth offset of the offset of the posting list. As postings
list offsets have always been sorted, we can then get to the closest
entry before the one we want an iterate forwards.
I haven't done much tuning on the 32 number, it was chosen to try
not to read through more than a 4k page of data.
Switch to a bulk interface for fetching postings. Use it to avoid having
to re-read parts of the posting offset table when querying lots of it.
For a index with what BenchmarkHeadPostingForMatchers uses RAM
for r.postings drops from 3.79MB to 80.19kB or about 48x.
Bytes allocated go down by 30%, and suprisingly CPU usage drops by
4-6% for typical queries too.
benchmark old ns/op new ns/op delta
BenchmarkPostingsForMatchers/Block/n="1"-4 35231 36673 +4.09%
BenchmarkPostingsForMatchers/Block/n="1",j="foo"-4 563380 540627 -4.04%
BenchmarkPostingsForMatchers/Block/j="foo",n="1"-4 536782 534186 -0.48%
BenchmarkPostingsForMatchers/Block/n="1",j!="foo"-4 533990 541550 +1.42%
BenchmarkPostingsForMatchers/Block/i=~".*"-4 113374598 117969608 +4.05%
BenchmarkPostingsForMatchers/Block/i=~".+"-4 146329884 139651442 -4.56%
BenchmarkPostingsForMatchers/Block/i=~""-4 50346510 44961127 -10.70%
BenchmarkPostingsForMatchers/Block/i!=""-4 41261550 35356165 -14.31%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",j="foo"-4 112544418 116904010 +3.87%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",i!="2",j="foo"-4 112487086 116864918 +3.89%
BenchmarkPostingsForMatchers/Block/n="1",i!=""-4 41094758 35457904 -13.72%
BenchmarkPostingsForMatchers/Block/n="1",i!="",j="foo"-4 41906372 36151473 -13.73%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",j="foo"-4 147262414 140424800 -4.64%
BenchmarkPostingsForMatchers/Block/n="1",i=~"1.+",j="foo"-4 28615629 27872072 -2.60%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!="2",j="foo"-4 147117177 140462403 -4.52%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!~"2.*",j="foo"-4 175096826 167902298 -4.11%
benchmark old allocs new allocs delta
BenchmarkPostingsForMatchers/Block/n="1"-4 4 6 +50.00%
BenchmarkPostingsForMatchers/Block/n="1",j="foo"-4 7 11 +57.14%
BenchmarkPostingsForMatchers/Block/j="foo",n="1"-4 7 11 +57.14%
BenchmarkPostingsForMatchers/Block/n="1",j!="foo"-4 15 17 +13.33%
BenchmarkPostingsForMatchers/Block/i=~".*"-4 100010 100012 +0.00%
BenchmarkPostingsForMatchers/Block/i=~".+"-4 200069 200040 -0.01%
BenchmarkPostingsForMatchers/Block/i=~""-4 200072 200045 -0.01%
BenchmarkPostingsForMatchers/Block/i!=""-4 200070 200041 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",j="foo"-4 100013 100017 +0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",i!="2",j="foo"-4 100017 100023 +0.01%
BenchmarkPostingsForMatchers/Block/n="1",i!=""-4 200073 200046 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i!="",j="foo"-4 200075 200050 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",j="foo"-4 200074 200049 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i=~"1.+",j="foo"-4 111165 111150 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!="2",j="foo"-4 200078 200055 -0.01%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!~"2.*",j="foo"-4 311282 311238 -0.01%
benchmark old bytes new bytes delta
BenchmarkPostingsForMatchers/Block/n="1"-4 264 296 +12.12%
BenchmarkPostingsForMatchers/Block/n="1",j="foo"-4 360 424 +17.78%
BenchmarkPostingsForMatchers/Block/j="foo",n="1"-4 360 424 +17.78%
BenchmarkPostingsForMatchers/Block/n="1",j!="foo"-4 520 552 +6.15%
BenchmarkPostingsForMatchers/Block/i=~".*"-4 1600461 1600482 +0.00%
BenchmarkPostingsForMatchers/Block/i=~".+"-4 24900801 17259077 -30.69%
BenchmarkPostingsForMatchers/Block/i=~""-4 24900836 17259151 -30.69%
BenchmarkPostingsForMatchers/Block/i!=""-4 24900760 17259048 -30.69%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",j="foo"-4 1600557 1600621 +0.00%
BenchmarkPostingsForMatchers/Block/n="1",i=~".*",i!="2",j="foo"-4 1600717 1600813 +0.01%
BenchmarkPostingsForMatchers/Block/n="1",i!=""-4 24900856 17259176 -30.69%
BenchmarkPostingsForMatchers/Block/n="1",i!="",j="foo"-4 24900952 17259304 -30.69%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",j="foo"-4 24900993 17259333 -30.69%
BenchmarkPostingsForMatchers/Block/n="1",i=~"1.+",j="foo"-4 3788311 3142630 -17.04%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!="2",j="foo"-4 24901137 17259509 -30.69%
BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!~"2.*",j="foo"-4 28693086 20405680 -28.88%
Signed-off-by: Brian Brazil <brian.brazil@robustperception.io>
2019-12-05 10:27:40 -08:00
|
|
|
return ix.Postings(m.Name, res...)
|
2019-05-27 04:24:46 -07:00
|
|
|
}
|
|
|
|
|
2017-01-06 03:37:28 -08:00
|
|
|
func mergeStrings(a, b []string) []string {
|
|
|
|
maxl := len(a)
|
|
|
|
if len(b) > len(a) {
|
|
|
|
maxl = len(b)
|
|
|
|
}
|
|
|
|
res := make([]string, 0, maxl*10/9)
|
|
|
|
|
|
|
|
for len(a) > 0 && len(b) > 0 {
|
|
|
|
d := strings.Compare(a[0], b[0])
|
|
|
|
|
|
|
|
if d == 0 {
|
|
|
|
res = append(res, a[0])
|
|
|
|
a, b = a[1:], b[1:]
|
|
|
|
} else if d < 0 {
|
|
|
|
res = append(res, a[0])
|
|
|
|
a = a[1:]
|
|
|
|
} else if d > 0 {
|
|
|
|
res = append(res, b[0])
|
|
|
|
b = b[1:]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Append all remaining elements.
|
|
|
|
res = append(res, a...)
|
|
|
|
res = append(res, b...)
|
|
|
|
return res
|
|
|
|
}
|
|
|
|
|
2019-11-15 06:45:29 -08:00
|
|
|
// mergedSeriesSet returns a series sets slice as a single series set. The input series sets
|
|
|
|
// must be sorted and sequential in time.
|
2020-02-06 07:58:38 -08:00
|
|
|
// TODO(bwplotka): Merge this with merge SeriesSet available in storage package.
|
2016-12-14 06:39:23 -08:00
|
|
|
type mergedSeriesSet struct {
|
2020-02-06 07:58:38 -08:00
|
|
|
all []storage.SeriesSet
|
|
|
|
buf []storage.SeriesSet // A buffer for keeping the order of SeriesSet slice during forwarding the SeriesSet.
|
|
|
|
ids []int // The indices of chosen SeriesSet for the current run.
|
2019-11-15 06:45:29 -08:00
|
|
|
done bool
|
|
|
|
err error
|
2020-02-06 07:58:38 -08:00
|
|
|
cur storage.Series
|
2016-12-14 06:39:23 -08:00
|
|
|
}
|
|
|
|
|
2020-02-06 07:58:38 -08:00
|
|
|
// TODO(bwplotka): Merge this with merge SeriesSet available in storage package.
|
|
|
|
func NewMergedSeriesSet(all []storage.SeriesSet) storage.SeriesSet {
|
2019-11-15 06:45:29 -08:00
|
|
|
if len(all) == 1 {
|
|
|
|
return all[0]
|
|
|
|
}
|
|
|
|
s := &mergedSeriesSet{all: all}
|
|
|
|
// Initialize first elements of all sets as Next() needs
|
2016-12-14 06:39:23 -08:00
|
|
|
// one element look-ahead.
|
2019-11-15 06:45:29 -08:00
|
|
|
s.nextAll()
|
|
|
|
if len(s.all) == 0 {
|
|
|
|
s.done = true
|
|
|
|
}
|
2016-12-14 06:39:23 -08:00
|
|
|
|
|
|
|
return s
|
|
|
|
}
|
|
|
|
|
2020-02-06 07:58:38 -08:00
|
|
|
func (s *mergedSeriesSet) At() storage.Series {
|
2016-12-14 06:39:23 -08:00
|
|
|
return s.cur
|
2016-12-13 06:26:58 -08:00
|
|
|
}
|
|
|
|
|
2017-03-14 07:24:08 -07:00
|
|
|
func (s *mergedSeriesSet) Err() error {
|
2019-11-15 06:45:29 -08:00
|
|
|
return s.err
|
|
|
|
}
|
|
|
|
|
|
|
|
// nextAll is to call Next() for all SeriesSet.
|
|
|
|
// Because the order of the SeriesSet slice will affect the results,
|
|
|
|
// we need to use an buffer slice to hold the order.
|
|
|
|
func (s *mergedSeriesSet) nextAll() {
|
|
|
|
s.buf = s.buf[:0]
|
|
|
|
for _, ss := range s.all {
|
|
|
|
if ss.Next() {
|
|
|
|
s.buf = append(s.buf, ss)
|
|
|
|
} else if ss.Err() != nil {
|
|
|
|
s.done = true
|
|
|
|
s.err = ss.Err()
|
|
|
|
break
|
|
|
|
}
|
2016-12-14 06:39:23 -08:00
|
|
|
}
|
2019-11-15 06:45:29 -08:00
|
|
|
s.all, s.buf = s.buf, s.all
|
2016-12-14 06:39:23 -08:00
|
|
|
}
|
2016-12-13 06:26:58 -08:00
|
|
|
|
2019-11-15 06:45:29 -08:00
|
|
|
// nextWithID is to call Next() for the SeriesSet with the indices of s.ids.
|
|
|
|
// Because the order of the SeriesSet slice will affect the results,
|
|
|
|
// we need to use an buffer slice to hold the order.
|
|
|
|
func (s *mergedSeriesSet) nextWithID() {
|
|
|
|
if len(s.ids) == 0 {
|
|
|
|
return
|
2016-12-14 06:39:23 -08:00
|
|
|
}
|
2019-11-15 06:45:29 -08:00
|
|
|
|
|
|
|
s.buf = s.buf[:0]
|
|
|
|
i1 := 0
|
|
|
|
i2 := 0
|
|
|
|
for i1 < len(s.all) {
|
|
|
|
if i2 < len(s.ids) && i1 == s.ids[i2] {
|
|
|
|
if !s.all[s.ids[i2]].Next() {
|
|
|
|
if s.all[s.ids[i2]].Err() != nil {
|
|
|
|
s.done = true
|
|
|
|
s.err = s.all[s.ids[i2]].Err()
|
|
|
|
break
|
|
|
|
}
|
|
|
|
i2++
|
|
|
|
i1++
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
i2++
|
|
|
|
}
|
|
|
|
s.buf = append(s.buf, s.all[i1])
|
|
|
|
i1++
|
2016-12-14 06:39:23 -08:00
|
|
|
}
|
2019-11-15 06:45:29 -08:00
|
|
|
s.all, s.buf = s.buf, s.all
|
2016-12-14 06:39:23 -08:00
|
|
|
}
|
|
|
|
|
2017-03-14 07:24:08 -07:00
|
|
|
func (s *mergedSeriesSet) Next() bool {
|
2019-11-15 06:45:29 -08:00
|
|
|
if s.done {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
s.nextWithID()
|
|
|
|
if s.done {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
s.ids = s.ids[:0]
|
|
|
|
if len(s.all) == 0 {
|
|
|
|
s.done = true
|
2016-12-14 06:39:23 -08:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2019-11-15 06:45:29 -08:00
|
|
|
// Here we are looking for a set of series sets with the lowest labels,
|
|
|
|
// and we will cache their indexes in s.ids.
|
|
|
|
s.ids = append(s.ids, 0)
|
|
|
|
for i := 1; i < len(s.all); i++ {
|
|
|
|
cmp := labels.Compare(s.all[s.ids[0]].At().Labels(), s.all[i].At().Labels())
|
|
|
|
if cmp > 0 {
|
|
|
|
s.ids = s.ids[:1]
|
|
|
|
s.ids[0] = i
|
|
|
|
} else if cmp == 0 {
|
|
|
|
s.ids = append(s.ids, i)
|
|
|
|
}
|
|
|
|
}
|
2017-01-04 00:47:20 -08:00
|
|
|
|
2019-11-15 06:45:29 -08:00
|
|
|
if len(s.ids) > 1 {
|
2020-02-06 07:58:38 -08:00
|
|
|
series := make([]storage.Series, len(s.ids))
|
2019-11-15 06:45:29 -08:00
|
|
|
for i, idx := range s.ids {
|
|
|
|
series[i] = s.all[idx].At()
|
|
|
|
}
|
|
|
|
s.cur = &chainedSeries{series: series}
|
2016-12-14 06:39:23 -08:00
|
|
|
} else {
|
2019-11-15 06:45:29 -08:00
|
|
|
s.cur = s.all[s.ids[0]].At()
|
2016-12-14 06:39:23 -08:00
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2019-02-14 05:29:41 -08:00
|
|
|
type mergedVerticalSeriesSet struct {
|
2020-02-06 07:58:38 -08:00
|
|
|
a, b storage.SeriesSet
|
|
|
|
cur storage.Series
|
2019-02-14 05:29:41 -08:00
|
|
|
adone, bdone bool
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewMergedVerticalSeriesSet takes two series sets as a single series set.
|
|
|
|
// The input series sets must be sorted and
|
|
|
|
// the time ranges of the series can be overlapping.
|
2020-02-06 07:58:38 -08:00
|
|
|
func NewMergedVerticalSeriesSet(a, b storage.SeriesSet) storage.SeriesSet {
|
2019-02-14 05:29:41 -08:00
|
|
|
return newMergedVerticalSeriesSet(a, b)
|
|
|
|
}
|
|
|
|
|
2020-02-06 07:58:38 -08:00
|
|
|
func newMergedVerticalSeriesSet(a, b storage.SeriesSet) *mergedVerticalSeriesSet {
|
2019-02-14 05:29:41 -08:00
|
|
|
s := &mergedVerticalSeriesSet{a: a, b: b}
|
|
|
|
// Initialize first elements of both sets as Next() needs
|
|
|
|
// one element look-ahead.
|
|
|
|
s.adone = !s.a.Next()
|
|
|
|
s.bdone = !s.b.Next()
|
|
|
|
|
|
|
|
return s
|
|
|
|
}
|
|
|
|
|
2020-02-06 07:58:38 -08:00
|
|
|
func (s *mergedVerticalSeriesSet) At() storage.Series {
|
2019-02-14 05:29:41 -08:00
|
|
|
return s.cur
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *mergedVerticalSeriesSet) Err() error {
|
|
|
|
if s.a.Err() != nil {
|
|
|
|
return s.a.Err()
|
|
|
|
}
|
|
|
|
return s.b.Err()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *mergedVerticalSeriesSet) compare() int {
|
|
|
|
if s.adone {
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
if s.bdone {
|
|
|
|
return -1
|
|
|
|
}
|
|
|
|
return labels.Compare(s.a.At().Labels(), s.b.At().Labels())
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *mergedVerticalSeriesSet) Next() bool {
|
|
|
|
if s.adone && s.bdone || s.Err() != nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
d := s.compare()
|
|
|
|
|
|
|
|
// Both sets contain the current series. Chain them into a single one.
|
|
|
|
if d > 0 {
|
|
|
|
s.cur = s.b.At()
|
|
|
|
s.bdone = !s.b.Next()
|
|
|
|
} else if d < 0 {
|
|
|
|
s.cur = s.a.At()
|
|
|
|
s.adone = !s.a.Next()
|
|
|
|
} else {
|
2020-02-06 07:58:38 -08:00
|
|
|
s.cur = &verticalChainedSeries{series: []storage.Series{s.a.At(), s.b.At()}}
|
2019-02-14 05:29:41 -08:00
|
|
|
s.adone = !s.a.Next()
|
|
|
|
s.bdone = !s.b.Next()
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2017-03-07 02:29:20 -08:00
|
|
|
// baseChunkSeries loads the label set and chunk references for a postings
|
|
|
|
// list from an index. It filters out series that have labels set that should be unset.
|
|
|
|
type baseChunkSeries struct {
|
2017-11-30 06:34:49 -08:00
|
|
|
p index.Postings
|
2017-05-17 02:19:42 -07:00
|
|
|
index IndexReader
|
2019-09-19 02:15:41 -07:00
|
|
|
tombstones tombstones.Reader
|
2017-05-17 02:19:42 -07:00
|
|
|
|
2017-05-22 04:12:36 -07:00
|
|
|
lset labels.Labels
|
2017-11-30 06:34:49 -08:00
|
|
|
chks []chunks.Meta
|
2019-09-19 02:15:41 -07:00
|
|
|
intervals tombstones.Intervals
|
2017-05-22 04:12:36 -07:00
|
|
|
err error
|
2017-05-17 02:19:42 -07:00
|
|
|
}
|
2017-03-07 02:29:20 -08:00
|
|
|
|
2017-11-13 04:57:10 -08:00
|
|
|
// LookupChunkSeries retrieves all series for the given matchers and returns a ChunkSeriesSet
|
|
|
|
// over them. It drops chunks based on tombstones in the given reader.
|
2020-02-06 07:58:38 -08:00
|
|
|
func LookupChunkSeries(ir IndexReader, tr tombstones.Reader, ms ...*labels.Matcher) (storage.ChunkSeriesSet, error) {
|
2020-01-17 03:21:44 -08:00
|
|
|
return lookupChunkSeries(false, ir, tr, ms...)
|
|
|
|
}
|
|
|
|
|
|
|
|
// LookupChunkSeries retrieves all series for the given matchers and returns a ChunkSeriesSet
|
|
|
|
// over them. It drops chunks based on tombstones in the given reader. Series will be in order.
|
2020-02-06 07:58:38 -08:00
|
|
|
func LookupChunkSeriesSorted(ir IndexReader, tr tombstones.Reader, ms ...*labels.Matcher) (storage.ChunkSeriesSet, error) {
|
2020-01-17 03:21:44 -08:00
|
|
|
return lookupChunkSeries(true, ir, tr, ms...)
|
|
|
|
}
|
|
|
|
|
2020-02-06 07:58:38 -08:00
|
|
|
func lookupChunkSeries(sorted bool, ir IndexReader, tr tombstones.Reader, ms ...*labels.Matcher) (storage.ChunkSeriesSet, error) {
|
2017-11-13 04:57:10 -08:00
|
|
|
if tr == nil {
|
2019-09-19 02:15:41 -07:00
|
|
|
tr = tombstones.NewMemTombstones()
|
2017-11-13 04:57:10 -08:00
|
|
|
}
|
2017-12-17 10:08:21 -08:00
|
|
|
p, err := PostingsForMatchers(ir, ms...)
|
2017-11-13 04:57:10 -08:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2020-01-17 03:21:44 -08:00
|
|
|
if sorted {
|
|
|
|
p = ir.SortedPostings(p)
|
|
|
|
}
|
2017-11-13 04:57:10 -08:00
|
|
|
return &baseChunkSeries{
|
|
|
|
p: p,
|
|
|
|
index: ir,
|
|
|
|
tombstones: tr,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2019-09-19 02:15:41 -07:00
|
|
|
func (s *baseChunkSeries) At() (labels.Labels, []chunks.Meta, tombstones.Intervals) {
|
2017-05-22 04:12:36 -07:00
|
|
|
return s.lset, s.chks, s.intervals
|
2016-12-14 06:39:23 -08:00
|
|
|
}
|
|
|
|
|
2017-05-17 02:19:42 -07:00
|
|
|
func (s *baseChunkSeries) Err() error { return s.err }
|
2017-03-07 02:29:20 -08:00
|
|
|
|
|
|
|
func (s *baseChunkSeries) Next() bool {
|
2017-08-05 04:31:48 -07:00
|
|
|
var (
|
2018-11-09 05:54:56 -08:00
|
|
|
lset = make(labels.Labels, len(s.lset))
|
|
|
|
chkMetas = make([]chunks.Meta, len(s.chks))
|
2017-11-30 06:34:49 -08:00
|
|
|
err error
|
2017-08-05 04:31:48 -07:00
|
|
|
)
|
2017-12-17 10:08:21 -08:00
|
|
|
|
2017-03-07 02:29:20 -08:00
|
|
|
for s.p.Next() {
|
2017-05-17 02:19:42 -07:00
|
|
|
ref := s.p.At()
|
2017-11-30 06:34:49 -08:00
|
|
|
if err := s.index.Series(ref, &lset, &chkMetas); err != nil {
|
2017-10-11 00:33:35 -07:00
|
|
|
// Postings may be stale. Skip if no underlying series exists.
|
|
|
|
if errors.Cause(err) == ErrNotFound {
|
|
|
|
continue
|
|
|
|
}
|
2016-12-16 03:13:17 -08:00
|
|
|
s.err = err
|
|
|
|
return false
|
|
|
|
}
|
2016-12-31 06:35:08 -08:00
|
|
|
|
2017-03-07 02:29:20 -08:00
|
|
|
s.lset = lset
|
2017-11-30 06:34:49 -08:00
|
|
|
s.chks = chkMetas
|
2017-11-13 04:32:24 -08:00
|
|
|
s.intervals, err = s.tombstones.Get(s.p.At())
|
|
|
|
if err != nil {
|
|
|
|
s.err = errors.Wrap(err, "get tombstones")
|
|
|
|
return false
|
|
|
|
}
|
2017-05-17 02:19:42 -07:00
|
|
|
|
2017-05-23 22:54:24 -07:00
|
|
|
if len(s.intervals) > 0 {
|
2017-05-17 02:19:42 -07:00
|
|
|
// Only those chunks that are not entirely deleted.
|
2017-11-30 06:34:49 -08:00
|
|
|
chks := make([]chunks.Meta, 0, len(s.chks))
|
2017-05-17 02:19:42 -07:00
|
|
|
for _, chk := range s.chks {
|
2019-09-19 02:15:41 -07:00
|
|
|
if !(tombstones.Interval{Mint: chk.MinTime, Maxt: chk.MaxTime}.IsSubrange(s.intervals)) {
|
2017-05-17 02:19:42 -07:00
|
|
|
chks = append(chks, chk)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
s.chks = chks
|
|
|
|
}
|
2017-03-07 02:29:20 -08:00
|
|
|
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
if err := s.p.Err(); err != nil {
|
|
|
|
s.err = err
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
// populatedChunkSeries loads chunk data from a store for a set of series
|
|
|
|
// with known chunk references. It filters out chunks that do not fit the
|
|
|
|
// given time range.
|
|
|
|
type populatedChunkSeries struct {
|
2020-02-06 07:58:38 -08:00
|
|
|
set storage.ChunkSeriesSet
|
2017-03-07 02:29:20 -08:00
|
|
|
chunks ChunkReader
|
|
|
|
mint, maxt int64
|
|
|
|
|
2017-05-22 04:12:36 -07:00
|
|
|
err error
|
2017-11-30 06:34:49 -08:00
|
|
|
chks []chunks.Meta
|
2017-05-22 04:12:36 -07:00
|
|
|
lset labels.Labels
|
2019-09-19 02:15:41 -07:00
|
|
|
intervals tombstones.Intervals
|
2017-03-07 02:29:20 -08:00
|
|
|
}
|
|
|
|
|
2019-09-19 02:15:41 -07:00
|
|
|
func (s *populatedChunkSeries) At() (labels.Labels, []chunks.Meta, tombstones.Intervals) {
|
2017-05-22 04:12:36 -07:00
|
|
|
return s.lset, s.chks, s.intervals
|
2017-05-17 02:19:42 -07:00
|
|
|
}
|
2017-12-13 12:58:21 -08:00
|
|
|
|
2017-05-17 02:19:42 -07:00
|
|
|
func (s *populatedChunkSeries) Err() error { return s.err }
|
2017-03-07 02:29:20 -08:00
|
|
|
|
|
|
|
func (s *populatedChunkSeries) Next() bool {
|
|
|
|
for s.set.Next() {
|
2017-05-22 04:12:36 -07:00
|
|
|
lset, chks, dranges := s.set.At()
|
2017-03-07 02:29:20 -08:00
|
|
|
|
2017-05-05 07:04:59 -07:00
|
|
|
for len(chks) > 0 {
|
|
|
|
if chks[0].MaxTime >= s.mint {
|
|
|
|
break
|
2016-12-31 06:35:08 -08:00
|
|
|
}
|
2017-05-05 07:04:59 -07:00
|
|
|
chks = chks[1:]
|
|
|
|
}
|
|
|
|
|
2017-12-13 12:58:21 -08:00
|
|
|
// This is to delete in place while iterating.
|
|
|
|
for i, rlen := 0, len(chks); i < rlen; i++ {
|
|
|
|
j := i - (rlen - len(chks))
|
|
|
|
c := &chks[j]
|
2017-08-06 11:41:24 -07:00
|
|
|
|
|
|
|
// Break out at the first chunk that has no overlap with mint, maxt.
|
2016-12-31 06:35:08 -08:00
|
|
|
if c.MinTime > s.maxt {
|
2017-12-13 12:58:21 -08:00
|
|
|
chks = chks[:j]
|
2016-12-31 06:35:08 -08:00
|
|
|
break
|
|
|
|
}
|
2017-12-13 12:58:21 -08:00
|
|
|
|
2017-03-07 02:29:20 -08:00
|
|
|
c.Chunk, s.err = s.chunks.Chunk(c.Ref)
|
|
|
|
if s.err != nil {
|
2017-12-13 12:58:21 -08:00
|
|
|
// This means that the chunk has be garbage collected. Remove it from the list.
|
|
|
|
if s.err == ErrNotFound {
|
|
|
|
s.err = nil
|
|
|
|
// Delete in-place.
|
2019-01-02 08:48:42 -08:00
|
|
|
s.chks = append(chks[:j], chks[j+1:]...)
|
2017-12-13 12:58:21 -08:00
|
|
|
}
|
2017-03-07 02:29:20 -08:00
|
|
|
return false
|
|
|
|
}
|
2016-12-31 06:35:08 -08:00
|
|
|
}
|
2017-12-13 12:58:21 -08:00
|
|
|
|
2017-03-07 02:29:20 -08:00
|
|
|
if len(chks) == 0 {
|
2016-12-31 06:35:08 -08:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2017-03-07 02:29:20 -08:00
|
|
|
s.lset = lset
|
|
|
|
s.chks = chks
|
2017-05-22 04:12:36 -07:00
|
|
|
s.intervals = dranges
|
2017-03-07 02:29:20 -08:00
|
|
|
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
if err := s.set.Err(); err != nil {
|
|
|
|
s.err = err
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
// blockSeriesSet is a set of series from an inverted index query.
|
|
|
|
type blockSeriesSet struct {
|
2020-02-06 07:58:38 -08:00
|
|
|
set storage.ChunkSeriesSet
|
2017-03-07 02:29:20 -08:00
|
|
|
err error
|
2020-02-06 07:58:38 -08:00
|
|
|
cur storage.Series
|
2017-04-13 12:06:14 -07:00
|
|
|
|
|
|
|
mint, maxt int64
|
2017-03-07 02:29:20 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *blockSeriesSet) Next() bool {
|
|
|
|
for s.set.Next() {
|
2017-05-22 04:12:36 -07:00
|
|
|
lset, chunks, dranges := s.set.At()
|
2017-05-17 02:19:42 -07:00
|
|
|
s.cur = &chunkSeries{
|
|
|
|
labels: lset,
|
|
|
|
chunks: chunks,
|
|
|
|
mint: s.mint,
|
|
|
|
maxt: s.maxt,
|
|
|
|
|
2017-05-22 04:12:36 -07:00
|
|
|
intervals: dranges,
|
2017-05-17 02:19:42 -07:00
|
|
|
}
|
2016-12-30 10:36:28 -08:00
|
|
|
return true
|
2016-12-14 06:39:23 -08:00
|
|
|
}
|
2017-03-07 02:29:20 -08:00
|
|
|
if s.set.Err() != nil {
|
|
|
|
s.err = s.set.Err()
|
2016-12-14 06:39:23 -08:00
|
|
|
}
|
2016-12-16 03:13:17 -08:00
|
|
|
return false
|
2016-12-14 06:39:23 -08:00
|
|
|
}
|
|
|
|
|
2020-02-06 07:58:38 -08:00
|
|
|
func (s *blockSeriesSet) At() storage.Series { return s.cur }
|
|
|
|
func (s *blockSeriesSet) Err() error { return s.err }
|
2016-12-14 06:39:23 -08:00
|
|
|
|
2016-12-19 03:26:25 -08:00
|
|
|
// chunkSeries is a series that is backed by a sequence of chunks holding
|
|
|
|
// time series data.
|
|
|
|
type chunkSeries struct {
|
2016-12-21 00:39:01 -08:00
|
|
|
labels labels.Labels
|
2017-11-30 06:34:49 -08:00
|
|
|
chunks []chunks.Meta // in-order chunk refs
|
2017-04-13 12:06:14 -07:00
|
|
|
|
|
|
|
mint, maxt int64
|
2017-05-17 02:19:42 -07:00
|
|
|
|
2019-09-19 02:15:41 -07:00
|
|
|
intervals tombstones.Intervals
|
2016-12-16 03:13:17 -08:00
|
|
|
}
|
|
|
|
|
2016-12-21 00:39:01 -08:00
|
|
|
func (s *chunkSeries) Labels() labels.Labels {
|
2016-12-16 03:13:17 -08:00
|
|
|
return s.labels
|
|
|
|
}
|
|
|
|
|
2020-02-06 07:58:38 -08:00
|
|
|
func (s *chunkSeries) Iterator() chunkenc.Iterator {
|
2017-05-22 04:12:36 -07:00
|
|
|
return newChunkSeriesIterator(s.chunks, s.intervals, s.mint, s.maxt)
|
2016-12-16 03:13:17 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
// chainedSeries implements a series for a list of time-sorted series.
|
2016-12-19 03:26:25 -08:00
|
|
|
// They all must have the same labels.
|
2016-12-14 06:39:23 -08:00
|
|
|
type chainedSeries struct {
|
2020-02-06 07:58:38 -08:00
|
|
|
series []storage.Series
|
2016-12-14 06:39:23 -08:00
|
|
|
}
|
|
|
|
|
2016-12-21 00:39:01 -08:00
|
|
|
func (s *chainedSeries) Labels() labels.Labels {
|
2016-12-14 06:39:23 -08:00
|
|
|
return s.series[0].Labels()
|
|
|
|
}
|
|
|
|
|
2020-02-06 07:58:38 -08:00
|
|
|
func (s *chainedSeries) Iterator() chunkenc.Iterator {
|
2017-04-09 07:00:25 -07:00
|
|
|
return newChainedSeriesIterator(s.series...)
|
2016-12-14 06:39:23 -08:00
|
|
|
}
|
|
|
|
|
2019-09-30 08:54:55 -07:00
|
|
|
// chainedSeriesIterator implements a series iterator over a list
|
2016-12-15 06:23:15 -08:00
|
|
|
// of time-sorted, non-overlapping iterators.
|
2016-12-14 06:39:23 -08:00
|
|
|
type chainedSeriesIterator struct {
|
2020-02-06 07:58:38 -08:00
|
|
|
series []storage.Series // series in time order
|
2016-12-15 06:23:15 -08:00
|
|
|
|
|
|
|
i int
|
2020-02-06 07:58:38 -08:00
|
|
|
cur chunkenc.Iterator
|
2016-12-14 06:39:23 -08:00
|
|
|
}
|
|
|
|
|
2020-02-06 07:58:38 -08:00
|
|
|
func newChainedSeriesIterator(s ...storage.Series) *chainedSeriesIterator {
|
2017-04-09 07:00:25 -07:00
|
|
|
return &chainedSeriesIterator{
|
|
|
|
series: s,
|
|
|
|
i: 0,
|
|
|
|
cur: s[0].Iterator(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-14 06:39:23 -08:00
|
|
|
func (it *chainedSeriesIterator) Seek(t int64) bool {
|
2016-12-16 03:13:17 -08:00
|
|
|
// We just scan the chained series sequentially as they are already
|
|
|
|
// pre-selected by relevant time and should be accessed sequentially anyway.
|
|
|
|
for i, s := range it.series[it.i:] {
|
|
|
|
cur := s.Iterator()
|
|
|
|
if !cur.Seek(t) {
|
|
|
|
continue
|
2016-12-15 06:23:15 -08:00
|
|
|
}
|
2016-12-16 03:13:17 -08:00
|
|
|
it.cur = cur
|
|
|
|
it.i += i
|
|
|
|
return true
|
2016-12-15 06:23:15 -08:00
|
|
|
}
|
2016-12-14 06:39:23 -08:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2016-12-15 06:23:15 -08:00
|
|
|
func (it *chainedSeriesIterator) Next() bool {
|
|
|
|
if it.cur.Next() {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
if err := it.cur.Err(); err != nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
if it.i == len(it.series)-1 {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
it.i++
|
2016-12-16 03:13:17 -08:00
|
|
|
it.cur = it.series[it.i].Iterator()
|
2016-12-15 06:23:15 -08:00
|
|
|
|
|
|
|
return it.Next()
|
2016-12-14 06:39:23 -08:00
|
|
|
}
|
|
|
|
|
2017-01-02 04:27:52 -08:00
|
|
|
func (it *chainedSeriesIterator) At() (t int64, v float64) {
|
|
|
|
return it.cur.At()
|
2016-12-14 06:39:23 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (it *chainedSeriesIterator) Err() error {
|
2016-12-15 06:23:15 -08:00
|
|
|
return it.cur.Err()
|
2016-12-14 06:39:23 -08:00
|
|
|
}
|
|
|
|
|
2019-02-14 05:29:41 -08:00
|
|
|
// verticalChainedSeries implements a series for a list of time-sorted, time-overlapping series.
|
|
|
|
// They all must have the same labels.
|
|
|
|
type verticalChainedSeries struct {
|
2020-02-06 07:58:38 -08:00
|
|
|
series []storage.Series
|
2019-02-14 05:29:41 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *verticalChainedSeries) Labels() labels.Labels {
|
|
|
|
return s.series[0].Labels()
|
|
|
|
}
|
|
|
|
|
2020-02-06 07:58:38 -08:00
|
|
|
func (s *verticalChainedSeries) Iterator() chunkenc.Iterator {
|
2019-02-14 05:29:41 -08:00
|
|
|
return newVerticalMergeSeriesIterator(s.series...)
|
|
|
|
}
|
|
|
|
|
2019-09-30 08:54:55 -07:00
|
|
|
// verticalMergeSeriesIterator implements a series iterator over a list
|
2019-02-14 05:29:41 -08:00
|
|
|
// of time-sorted, time-overlapping iterators.
|
|
|
|
type verticalMergeSeriesIterator struct {
|
2020-02-06 07:58:38 -08:00
|
|
|
a, b chunkenc.Iterator
|
2019-02-14 05:29:41 -08:00
|
|
|
aok, bok, initialized bool
|
|
|
|
|
|
|
|
curT int64
|
|
|
|
curV float64
|
|
|
|
}
|
|
|
|
|
2020-02-06 07:58:38 -08:00
|
|
|
func newVerticalMergeSeriesIterator(s ...storage.Series) chunkenc.Iterator {
|
2019-02-14 05:29:41 -08:00
|
|
|
if len(s) == 1 {
|
|
|
|
return s[0].Iterator()
|
|
|
|
} else if len(s) == 2 {
|
|
|
|
return &verticalMergeSeriesIterator{
|
|
|
|
a: s[0].Iterator(),
|
|
|
|
b: s[1].Iterator(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return &verticalMergeSeriesIterator{
|
|
|
|
a: s[0].Iterator(),
|
|
|
|
b: newVerticalMergeSeriesIterator(s[1:]...),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (it *verticalMergeSeriesIterator) Seek(t int64) bool {
|
|
|
|
it.aok, it.bok = it.a.Seek(t), it.b.Seek(t)
|
|
|
|
it.initialized = true
|
|
|
|
return it.Next()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (it *verticalMergeSeriesIterator) Next() bool {
|
|
|
|
if !it.initialized {
|
|
|
|
it.aok = it.a.Next()
|
|
|
|
it.bok = it.b.Next()
|
|
|
|
it.initialized = true
|
|
|
|
}
|
|
|
|
|
|
|
|
if !it.aok && !it.bok {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
if !it.aok {
|
|
|
|
it.curT, it.curV = it.b.At()
|
|
|
|
it.bok = it.b.Next()
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
if !it.bok {
|
|
|
|
it.curT, it.curV = it.a.At()
|
|
|
|
it.aok = it.a.Next()
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
acurT, acurV := it.a.At()
|
|
|
|
bcurT, bcurV := it.b.At()
|
|
|
|
if acurT < bcurT {
|
|
|
|
it.curT, it.curV = acurT, acurV
|
|
|
|
it.aok = it.a.Next()
|
|
|
|
} else if acurT > bcurT {
|
|
|
|
it.curT, it.curV = bcurT, bcurV
|
|
|
|
it.bok = it.b.Next()
|
|
|
|
} else {
|
|
|
|
it.curT, it.curV = bcurT, bcurV
|
|
|
|
it.aok = it.a.Next()
|
|
|
|
it.bok = it.b.Next()
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
func (it *verticalMergeSeriesIterator) At() (t int64, v float64) {
|
|
|
|
return it.curT, it.curV
|
|
|
|
}
|
|
|
|
|
|
|
|
func (it *verticalMergeSeriesIterator) Err() error {
|
|
|
|
if it.a.Err() != nil {
|
|
|
|
return it.a.Err()
|
|
|
|
}
|
|
|
|
return it.b.Err()
|
|
|
|
}
|
|
|
|
|
2016-12-12 10:12:55 -08:00
|
|
|
// chunkSeriesIterator implements a series iterator on top
|
|
|
|
// of a list of time-sorted, non-overlapping chunks.
|
|
|
|
type chunkSeriesIterator struct {
|
2017-11-30 06:34:49 -08:00
|
|
|
chunks []chunks.Meta
|
2016-12-12 10:12:55 -08:00
|
|
|
|
2019-07-09 02:49:34 -07:00
|
|
|
i int
|
|
|
|
cur chunkenc.Iterator
|
|
|
|
bufDelIter *deletedIterator
|
2017-04-13 12:06:14 -07:00
|
|
|
|
|
|
|
maxt, mint int64
|
2017-05-17 02:19:42 -07:00
|
|
|
|
2019-09-19 02:15:41 -07:00
|
|
|
intervals tombstones.Intervals
|
2016-12-12 10:12:55 -08:00
|
|
|
}
|
|
|
|
|
2019-09-19 02:15:41 -07:00
|
|
|
func newChunkSeriesIterator(cs []chunks.Meta, dranges tombstones.Intervals, mint, maxt int64) *chunkSeriesIterator {
|
2019-07-09 02:49:34 -07:00
|
|
|
csi := &chunkSeriesIterator{
|
2016-12-12 10:12:55 -08:00
|
|
|
chunks: cs,
|
|
|
|
i: 0,
|
2017-04-13 12:06:14 -07:00
|
|
|
|
|
|
|
mint: mint,
|
|
|
|
maxt: maxt,
|
2017-05-17 02:19:42 -07:00
|
|
|
|
2017-05-22 04:12:36 -07:00
|
|
|
intervals: dranges,
|
2016-12-12 10:12:55 -08:00
|
|
|
}
|
2019-07-09 02:49:34 -07:00
|
|
|
csi.resetCurIterator()
|
|
|
|
|
|
|
|
return csi
|
|
|
|
}
|
|
|
|
|
|
|
|
func (it *chunkSeriesIterator) resetCurIterator() {
|
|
|
|
if len(it.intervals) == 0 {
|
|
|
|
it.cur = it.chunks[it.i].Chunk.Iterator(it.cur)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if it.bufDelIter == nil {
|
|
|
|
it.bufDelIter = &deletedIterator{
|
|
|
|
intervals: it.intervals,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
it.bufDelIter.it = it.chunks[it.i].Chunk.Iterator(it.bufDelIter.it)
|
|
|
|
it.cur = it.bufDelIter
|
2016-12-12 10:12:55 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (it *chunkSeriesIterator) Seek(t int64) (ok bool) {
|
2017-04-13 12:07:21 -07:00
|
|
|
if t > it.maxt {
|
2017-04-13 12:06:14 -07:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2017-04-13 12:07:21 -07:00
|
|
|
// Seek to the first valid value after t.
|
|
|
|
if t < it.mint {
|
|
|
|
t = it.mint
|
|
|
|
}
|
|
|
|
|
2017-06-30 06:06:27 -07:00
|
|
|
for ; it.chunks[it.i].MaxTime < t; it.i++ {
|
|
|
|
if it.i == len(it.chunks)-1 {
|
|
|
|
return false
|
|
|
|
}
|
2016-12-15 06:23:15 -08:00
|
|
|
}
|
|
|
|
|
2019-07-09 02:49:34 -07:00
|
|
|
it.resetCurIterator()
|
2016-12-15 06:23:15 -08:00
|
|
|
|
|
|
|
for it.cur.Next() {
|
2017-01-02 04:27:52 -08:00
|
|
|
t0, _ := it.cur.At()
|
2016-12-15 06:23:15 -08:00
|
|
|
if t0 >= t {
|
2016-12-16 03:13:17 -08:00
|
|
|
return true
|
2016-12-12 10:12:55 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2017-01-02 04:27:52 -08:00
|
|
|
func (it *chunkSeriesIterator) At() (t int64, v float64) {
|
|
|
|
return it.cur.At()
|
2016-12-12 10:12:55 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (it *chunkSeriesIterator) Next() bool {
|
2017-08-28 15:39:17 -07:00
|
|
|
if it.cur.Next() {
|
2017-04-13 12:06:14 -07:00
|
|
|
t, _ := it.cur.At()
|
2017-08-28 15:39:17 -07:00
|
|
|
|
2017-06-12 22:54:04 -07:00
|
|
|
if t < it.mint {
|
2017-08-28 15:39:17 -07:00
|
|
|
if !it.Seek(it.mint) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
t, _ = it.At()
|
2017-06-12 22:54:04 -07:00
|
|
|
|
2017-08-28 15:39:17 -07:00
|
|
|
return t <= it.maxt
|
|
|
|
}
|
2017-06-12 22:54:04 -07:00
|
|
|
if t > it.maxt {
|
|
|
|
return false
|
2017-04-13 12:06:14 -07:00
|
|
|
}
|
2017-06-12 22:54:04 -07:00
|
|
|
return true
|
2016-12-12 10:12:55 -08:00
|
|
|
}
|
|
|
|
if err := it.cur.Err(); err != nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
if it.i == len(it.chunks)-1 {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
it.i++
|
2019-07-09 02:49:34 -07:00
|
|
|
it.resetCurIterator()
|
2016-12-12 10:12:55 -08:00
|
|
|
|
|
|
|
return it.Next()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (it *chunkSeriesIterator) Err() error {
|
|
|
|
return it.cur.Err()
|
|
|
|
}
|
|
|
|
|
2017-11-30 06:34:49 -08:00
|
|
|
// deletedIterator wraps an Iterator and makes sure any deleted metrics are not
|
|
|
|
// returned.
|
|
|
|
type deletedIterator struct {
|
|
|
|
it chunkenc.Iterator
|
|
|
|
|
2019-09-19 02:15:41 -07:00
|
|
|
intervals tombstones.Intervals
|
2017-11-30 06:34:49 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (it *deletedIterator) At() (int64, float64) {
|
|
|
|
return it.it.At()
|
|
|
|
}
|
|
|
|
|
2020-02-06 07:58:38 -08:00
|
|
|
func (it *deletedIterator) Seek(t int64) bool {
|
|
|
|
if it.it.Err() != nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return it.it.Seek(t)
|
|
|
|
}
|
|
|
|
|
2017-11-30 06:34:49 -08:00
|
|
|
func (it *deletedIterator) Next() bool {
|
|
|
|
Outer:
|
|
|
|
for it.it.Next() {
|
|
|
|
ts, _ := it.it.At()
|
|
|
|
|
|
|
|
for _, tr := range it.intervals {
|
2019-09-19 02:15:41 -07:00
|
|
|
if tr.InBounds(ts) {
|
2017-11-30 06:34:49 -08:00
|
|
|
continue Outer
|
|
|
|
}
|
|
|
|
|
2020-02-06 07:58:38 -08:00
|
|
|
if ts <= tr.Maxt {
|
|
|
|
return true
|
2017-11-30 06:34:49 -08:00
|
|
|
|
2020-02-06 07:58:38 -08:00
|
|
|
}
|
|
|
|
it.intervals = it.intervals[1:]
|
2017-11-30 06:34:49 -08:00
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2020-02-06 07:58:38 -08:00
|
|
|
func (it *deletedIterator) Err() error { return it.it.Err() }
|