mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2026-05-17 00:26:36 +03:00
Benchmarking storage search api requires taking into account many parameters, such as: - data configuration: how many series, deleted series, search time range - where the index data recides: prev and or indexDB - which search operation to measure While adding a new benchmark use case involves a lot boilerplate code. This pr implements a framework for testing storage search ops that can be relatively easily extended. This come in expecially handy when adding new cases for parition index. The current set of params will result of a lot of benchmarks to be run which most probably does not make sense because: - it will take a lot of time and - the output data is hard to compare manually. However, these benchmarks are very useful when only small set of params is of interest. For example, if I want to compare the search of 100k metric names when the index data resides in prevOnly, currOnly or prevAndCurr indexDBs. This would translate in the following cmd: ```shell go test ./lib/storage --loggerLevel=ERROR -run=^$ -bench=^BenchmarkSearch/MetricNames/.*/VariableSeries/100000$ ``` Why this change: - I often need to run benchmarks with configs that I did not have before, requires either modifying the existing one or writing a new one. It is easy to get lost and make benchmark non-comparable - I need some way to make legacy and pt index benchmarks comparable Signed-off-by: Artem Fetishev <rtm@victoriametrics.com>
68 lines
1.8 KiB
Go
68 lines
1.8 KiB
Go
package storage
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/google/go-cmp/cmp"
|
|
)
|
|
|
|
// benchmarkSearchData measures the search of all data on the given time range.
|
|
// It also ensures that the search result is correct by comparing it with metric
|
|
// rows stored in the database.
|
|
func benchmarkSearchData(b *testing.B, s *Storage, tr TimeRange, mrs []MetricRow) {
|
|
b.Helper()
|
|
tfss := NewTagFilters()
|
|
if err := tfss.Add([]byte("__name__"), []byte(".*"), false, true); err != nil {
|
|
b.Fatalf("unexpected error in TagFilters.Add: %v", err)
|
|
}
|
|
|
|
type metricBlock struct {
|
|
MetricName []byte
|
|
Block *Block
|
|
}
|
|
mbs := make([]metricBlock, 0, len(mrs))
|
|
for b.Loop() {
|
|
mbs = mbs[:0]
|
|
var search Search
|
|
search.Init(nil, s, []*TagFilters{tfss}, tr, 1e9, noDeadline)
|
|
for search.NextMetricBlock() {
|
|
var (
|
|
block Block
|
|
mb metricBlock
|
|
)
|
|
search.MetricBlockRef.BlockRef.MustReadBlock(&block)
|
|
mb.MetricName = append(mb.MetricName, search.MetricBlockRef.MetricName...)
|
|
mb.Block = &block
|
|
mbs = append(mbs, mb)
|
|
}
|
|
if err := search.Error(); err != nil {
|
|
b.Fatalf("search error: %v", err)
|
|
}
|
|
search.MustClose()
|
|
}
|
|
|
|
var mn MetricName
|
|
got := make([]MetricRow, len(mrs))
|
|
for i, mb := range mbs {
|
|
rb := newTestRawBlock(mb.Block, tr)
|
|
if err := mn.Unmarshal(mb.MetricName); err != nil {
|
|
b.Fatalf("cannot unmarshal MetricName %v: %v", string(mb.MetricName), err)
|
|
}
|
|
metricNameRaw := mn.marshalRaw(nil)
|
|
for j, timestamp := range rb.Timestamps {
|
|
mr := MetricRow{
|
|
MetricNameRaw: metricNameRaw,
|
|
Timestamp: timestamp,
|
|
Value: rb.Values[j],
|
|
}
|
|
got[i] = mr
|
|
}
|
|
}
|
|
testSortMetricRows(got)
|
|
want := mrs
|
|
testSortMetricRows(want)
|
|
if diff := cmp.Diff(mrsToString(want), mrsToString(got)); diff != "" {
|
|
b.Errorf("unexpected metric rows (-want, +got):\n%s", diff)
|
|
}
|
|
}
|