Optimization on `mergedStringIter` (#12132)

Optimization on NewMergedStringIter

Signed-off-by: Alan Protasio <alanprot@gmail.com>
This commit is contained in:
Alan Protasio 2023-03-27 04:40:45 -07:00 committed by GitHub
parent 3ac49d4ae2
commit 6ddadd98b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 35 additions and 6 deletions

View File

@ -958,6 +958,7 @@ type mergedStringIter struct {
b index.StringIter
aok, bok bool
cur string
err error
}
func (m *mergedStringIter) Next() bool {
@ -968,29 +969,34 @@ func (m *mergedStringIter) Next() bool {
if !m.aok {
m.cur = m.b.At()
m.bok = m.b.Next()
m.err = m.b.Err()
} else if !m.bok {
m.cur = m.a.At()
m.aok = m.a.Next()
m.err = m.a.Err()
} else if m.b.At() > m.a.At() {
m.cur = m.a.At()
m.aok = m.a.Next()
m.err = m.a.Err()
} else if m.a.At() > m.b.At() {
m.cur = m.b.At()
m.bok = m.b.Next()
m.err = m.b.Err()
} else { // Equal.
m.cur = m.b.At()
m.aok = m.a.Next()
m.err = m.a.Err()
m.bok = m.b.Next()
if m.err == nil {
m.err = m.b.Err()
}
}
return true
}
func (m mergedStringIter) At() string { return m.cur }
func (m mergedStringIter) Err() error {
if m.a.Err() != nil {
return m.a.Err()
}
return m.b.Err()
return m.err
}
// DeletedIterator wraps chunk Iterator and makes sure any deleted metrics are not returned.

View File

@ -19,9 +19,10 @@ import (
"strconv"
"testing"
"github.com/stretchr/testify/require"
"github.com/prometheus/prometheus/model/labels"
"github.com/prometheus/prometheus/tsdb/index"
"github.com/stretchr/testify/require"
)
// Make entries ~50B in size, to emulate real-world high cardinality.
@ -202,6 +203,28 @@ func benchmarkLabelValuesWithMatchers(b *testing.B, ir IndexReader) {
}
}
func BenchmarkMergedStringIter(b *testing.B) {
numSymbols := 100000
s := make([]string, numSymbols)
for i := 0; i < numSymbols; i++ {
s[i] = fmt.Sprintf("symbol%v", i)
}
for i := 0; i < b.N; i++ {
it := NewMergedStringIter(index.NewStringListIter(s), index.NewStringListIter(s))
for j := 0; j < 100; j++ {
it = NewMergedStringIter(it, index.NewStringListIter(s))
}
for it.Next() {
require.NotNil(b, it.At())
require.NoError(b, it.Err())
}
}
b.ReportAllocs()
}
func BenchmarkQuerierSelect(b *testing.B) {
chunkDir := b.TempDir()
opts := DefaultHeadOptions()