2019-05-22 21:16:55 +00:00
|
|
|
package storage
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"math/rand"
|
|
|
|
"os"
|
2023-03-25 21:33:54 +00:00
|
|
|
"path/filepath"
|
2019-05-22 21:16:55 +00:00
|
|
|
"sync"
|
|
|
|
"sync/atomic"
|
|
|
|
"testing"
|
|
|
|
"time"
|
2020-12-08 18:49:32 +00:00
|
|
|
|
|
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/cgroup"
|
2019-05-22 21:16:55 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestMain(m *testing.M) {
|
2023-04-15 03:52:36 +00:00
|
|
|
isDebug = true
|
2019-05-22 21:16:55 +00:00
|
|
|
n := m.Run()
|
2023-03-25 21:33:54 +00:00
|
|
|
if err := os.RemoveAll("benchmarkTableSearch"); err != nil {
|
2020-06-30 19:58:18 +00:00
|
|
|
panic(fmt.Errorf("cannot remove benchmark tables: %w", err))
|
2019-05-22 21:16:55 +00:00
|
|
|
}
|
|
|
|
os.Exit(n)
|
|
|
|
}
|
|
|
|
|
|
|
|
func BenchmarkTableSearch(b *testing.B) {
|
|
|
|
for _, rowsCount := range []int{1e5, 1e6, 1e7, 1e8} {
|
|
|
|
b.Run(fmt.Sprintf("rowsCount_%d", rowsCount), func(b *testing.B) {
|
|
|
|
for _, tsidsCount := range []int{1e3, 1e4} {
|
|
|
|
b.Run(fmt.Sprintf("tsidsCount_%d", tsidsCount), func(b *testing.B) {
|
|
|
|
for _, tsidsSearch := range []int{1, 1e1, 1e2, 1e3, 1e4} {
|
|
|
|
b.Run(fmt.Sprintf("tsidsSearch_%d", tsidsSearch), func(b *testing.B) {
|
2022-06-28 09:55:20 +00:00
|
|
|
benchmarkTableSearch(b, rowsCount, tsidsCount, tsidsSearch)
|
2019-05-22 21:16:55 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func openBenchTable(b *testing.B, startTimestamp int64, rowsPerInsert, rowsCount, tsidsCount int) *table {
|
|
|
|
b.Helper()
|
|
|
|
|
2023-03-25 21:33:54 +00:00
|
|
|
path := filepath.Join("benchmarkTableSearch", fmt.Sprintf("rows%d_tsids%d", rowsCount, tsidsCount))
|
2019-05-22 21:16:55 +00:00
|
|
|
if !createdBenchTables[path] {
|
|
|
|
createBenchTable(b, path, startTimestamp, rowsPerInsert, rowsCount, tsidsCount)
|
|
|
|
createdBenchTables[path] = true
|
|
|
|
}
|
2022-10-23 13:23:44 +00:00
|
|
|
strg := newTestStorage()
|
2022-10-23 22:30:50 +00:00
|
|
|
tb, err := openTable(path, strg)
|
2019-05-22 21:16:55 +00:00
|
|
|
if err != nil {
|
|
|
|
b.Fatalf("cnanot open table %q: %s", path, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify rows count in the table opened from files.
|
|
|
|
insertsCount := uint64((rowsCount + rowsPerInsert - 1) / rowsPerInsert)
|
|
|
|
rowsCountExpected := insertsCount * uint64(rowsPerInsert)
|
|
|
|
var m TableMetrics
|
|
|
|
tb.UpdateMetrics(&m)
|
2022-12-05 23:15:00 +00:00
|
|
|
if rowsCount := m.TotalRowsCount(); rowsCount != rowsCountExpected {
|
|
|
|
b.Fatalf("unexpected rows count in the table %q; got %d; want %d", path, rowsCount, rowsCountExpected)
|
2019-05-22 21:16:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return tb
|
|
|
|
}
|
|
|
|
|
|
|
|
var createdBenchTables = make(map[string]bool)
|
|
|
|
|
|
|
|
func createBenchTable(b *testing.B, path string, startTimestamp int64, rowsPerInsert, rowsCount, tsidsCount int) {
|
|
|
|
b.Helper()
|
|
|
|
|
2022-10-23 13:23:44 +00:00
|
|
|
strg := newTestStorage()
|
2022-10-23 22:30:50 +00:00
|
|
|
tb, err := openTable(path, strg)
|
2019-05-22 21:16:55 +00:00
|
|
|
if err != nil {
|
|
|
|
b.Fatalf("cannot open table %q: %s", path, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
insertsCount := uint64((rowsCount + rowsPerInsert - 1) / rowsPerInsert)
|
|
|
|
timestamp := uint64(startTimestamp)
|
|
|
|
|
|
|
|
var wg sync.WaitGroup
|
2020-12-08 18:49:32 +00:00
|
|
|
for k := 0; k < cgroup.AvailableCPUs(); k++ {
|
2019-05-22 21:16:55 +00:00
|
|
|
wg.Add(1)
|
2023-01-24 04:10:29 +00:00
|
|
|
go func(n int) {
|
|
|
|
rng := rand.New(rand.NewSource(int64(n)))
|
2019-05-22 21:16:55 +00:00
|
|
|
rows := make([]rawRow, rowsPerInsert)
|
|
|
|
value := float64(100)
|
|
|
|
for int(atomic.AddUint64(&insertsCount, ^uint64(0))) >= 0 {
|
|
|
|
for j := 0; j < rowsPerInsert; j++ {
|
2023-01-24 04:10:29 +00:00
|
|
|
ts := atomic.AddUint64(×tamp, uint64(10+rng.Int63n(2)))
|
|
|
|
value += float64(int(rng.NormFloat64() * 5))
|
2019-05-22 21:16:55 +00:00
|
|
|
|
|
|
|
r := &rows[j]
|
|
|
|
r.PrecisionBits = defaultPrecisionBits
|
2023-01-24 04:10:29 +00:00
|
|
|
r.TSID.MetricID = uint64(rng.Intn(tsidsCount) + 1)
|
2019-05-22 21:16:55 +00:00
|
|
|
r.Timestamp = int64(ts)
|
|
|
|
r.Value = value
|
|
|
|
}
|
2023-04-14 05:11:56 +00:00
|
|
|
tb.MustAddRows(rows)
|
2019-05-22 21:16:55 +00:00
|
|
|
}
|
|
|
|
wg.Done()
|
2023-01-24 04:10:29 +00:00
|
|
|
}(k)
|
2019-05-22 21:16:55 +00:00
|
|
|
}
|
|
|
|
wg.Wait()
|
|
|
|
|
|
|
|
tb.MustClose()
|
|
|
|
}
|
|
|
|
|
2022-06-28 09:55:20 +00:00
|
|
|
func benchmarkTableSearch(b *testing.B, rowsCount, tsidsCount, tsidsSearch int) {
|
2019-05-22 21:16:55 +00:00
|
|
|
startTimestamp := timestampFromTime(time.Now()) - 365*24*3600*1000
|
2021-06-11 07:52:14 +00:00
|
|
|
rowsPerInsert := getMaxRawRowsPerShard()
|
2019-05-22 21:16:55 +00:00
|
|
|
|
|
|
|
tb := openBenchTable(b, startTimestamp, rowsPerInsert, rowsCount, tsidsCount)
|
|
|
|
tr := TimeRange{
|
|
|
|
MinTimestamp: startTimestamp,
|
|
|
|
MaxTimestamp: (1 << 63) - 1,
|
|
|
|
}
|
|
|
|
|
|
|
|
b.ResetTimer()
|
|
|
|
b.ReportAllocs()
|
|
|
|
rowsPerBench := int64(float64(rowsCount) * float64(tsidsSearch) / float64(tsidsCount))
|
|
|
|
if rowsPerBench > int64(rowsCount) {
|
|
|
|
rowsPerBench = int64(rowsCount)
|
|
|
|
}
|
|
|
|
b.SetBytes(rowsPerBench)
|
|
|
|
b.RunParallel(func(pb *testing.PB) {
|
|
|
|
var ts tableSearch
|
|
|
|
tsids := make([]TSID, tsidsSearch)
|
2020-04-27 05:13:41 +00:00
|
|
|
var tmpBlock Block
|
2019-05-22 21:16:55 +00:00
|
|
|
for pb.Next() {
|
|
|
|
for i := range tsids {
|
|
|
|
tsids[i].MetricID = 1 + uint64(i)
|
|
|
|
}
|
2020-04-27 05:13:41 +00:00
|
|
|
ts.Init(tb, tsids, tr)
|
2019-05-22 21:16:55 +00:00
|
|
|
for ts.NextBlock() {
|
2022-06-28 09:55:20 +00:00
|
|
|
ts.BlockRef.MustReadBlock(&tmpBlock)
|
2019-05-22 21:16:55 +00:00
|
|
|
}
|
|
|
|
ts.MustClose()
|
|
|
|
}
|
|
|
|
})
|
|
|
|
b.StopTimer()
|
|
|
|
|
|
|
|
tb.MustClose()
|
|
|
|
}
|