chore(tsm1): Add benchmarks for existing typed decoders
These benchmarks will be implemented in batched decoders to compare performance.pull/10084/head
parent
75e0bca597
commit
7948a8e217
|
@ -0,0 +1,105 @@
|
|||
package testutil
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// MakeSentence returns a string made up of n words.
|
||||
// MakeSentence uses rand.Int31n and therefore calling rand.Seed will produce
|
||||
// deterministic results.
|
||||
func MakeSentence(n int) string {
|
||||
s := make([]string, n)
|
||||
for i := 0; i < n; i++ {
|
||||
s[i] = words[rand.Int31n(int32(len(words)))]
|
||||
}
|
||||
return strings.Join(s, " ")
|
||||
}
|
||||
|
||||
var words = [...]string{
|
||||
"lorem", "ipsum", "dolor", "sit", "amet", "consectetuer", "adipiscing", "elit", "integer", "in", "mi", "a", "mauris",
|
||||
"ornare", "sagittis", "suspendisse", "potenti", "suspendisse", "dapibus", "dignissim", "dolor", "nam",
|
||||
"sapien", "tellus", "tempus", "et", "tempus", "ac", "tincidunt", "in", "arcu", "duis", "dictum", "proin", "magna",
|
||||
"nulla", "pellentesque", "non", "commodo", "et", "iaculis", "sit", "amet", "mi", "mauris", "condimentum", "massa",
|
||||
"ut", "metus", "donec", "viverra", "sapien", "mattis", "rutrum", "tristique", "lacus", "eros", "semper", "tellus",
|
||||
"et", "molestie", "nisi", "sapien", "eu", "massa", "vestibulum", "ante", "ipsum", "primis", "in", "faucibus", "orci",
|
||||
"luctus", "et", "ultrices", "posuere", "cubilia", "curae", "fusce", "erat", "tortor", "mollis", "ut", "accumsan",
|
||||
"ut", "lacinia", "gravida", "libero", "curabitur", "massa", "felis", "accumsan", "feugiat", "convallis", "sit",
|
||||
"amet", "porta", "vel", "neque", "duis", "et", "ligula", "non", "elit", "ultricies", "rutrum", "suspendisse",
|
||||
"tempor", "quisque", "posuere", "malesuada", "velit", "sed", "pellentesque", "mi", "a", "purus", "integer",
|
||||
"imperdiet", "orci", "a", "eleifend", "mollis", "velit", "nulla", "iaculis", "arcu", "eu", "rutrum", "magna", "quam",
|
||||
"sed", "elit", "nullam", "egestas", "integer", "interdum", "purus", "nec", "mauris", "vestibulum", "ac", "mi", "in",
|
||||
"nunc", "suscipit", "dapibus", "duis", "consectetuer", "ipsum", "et", "pharetra", "sollicitudin", "metus",
|
||||
"turpis", "facilisis", "magna", "vitae", "dictum", "ligula", "nulla", "nec", "mi", "nunc", "ante", "urna", "gravida",
|
||||
"sit", "amet", "congue", "et", "accumsan", "vitae", "magna", "praesent", "luctus", "nullam", "in", "velit",
|
||||
"praesent", "est", "curabitur", "turpis", "class", "aptent", "taciti", "sociosqu", "ad", "litora", "torquent",
|
||||
"per", "conubia", "nostra", "per", "inceptos", "hymenaeos", "cras", "consectetuer", "nibh", "in", "lacinia",
|
||||
"ornare", "turpis", "sem", "tempor", "massa", "sagittis", "feugiat", "mauris", "nibh", "non", "tellus",
|
||||
"phasellus", "mi", "fusce", "enim", "mauris", "ultrices", "turpis", "eu", "adipiscing", "viverra", "justo",
|
||||
"libero", "ullamcorper", "massa", "id", "ultrices", "velit", "est", "quis", "tortor", "quisque", "condimentum",
|
||||
"lacus", "volutpat", "nonummy", "accumsan", "est", "nunc", "imperdiet", "magna", "vulputate", "aliquet", "nisi",
|
||||
"risus", "at", "est", "aliquam", "imperdiet", "gravida", "tortor", "praesent", "interdum", "accumsan", "ante",
|
||||
"vivamus", "est", "ligula", "consequat", "sed", "pulvinar", "eu", "consequat", "vitae", "eros", "nulla", "elit",
|
||||
"nunc", "congue", "eget", "scelerisque", "a", "tempor", "ac", "nisi", "morbi", "facilisis", "pellentesque",
|
||||
"habitant", "morbi", "tristique", "senectus", "et", "netus", "et", "malesuada", "fames", "ac", "turpis", "egestas",
|
||||
"in", "hac", "habitasse", "platea", "dictumst", "suspendisse", "vel", "lorem", "ut", "ligula", "tempor",
|
||||
"consequat", "quisque", "consectetuer", "nisl", "eget", "elit", "proin", "quis", "mauris", "ac", "orci",
|
||||
"accumsan", "suscipit", "sed", "ipsum", "sed", "vel", "libero", "nec", "elit", "feugiat", "blandit", "vestibulum",
|
||||
"purus", "nulla", "accumsan", "et", "volutpat", "at", "pellentesque", "vel", "urna", "suspendisse", "nonummy",
|
||||
"aliquam", "pulvinar", "libero", "donec", "vulputate", "orci", "ornare", "bibendum", "condimentum", "lorem",
|
||||
"elit", "dignissim", "sapien", "ut", "aliquam", "nibh", "augue", "in", "turpis", "phasellus", "ac", "eros",
|
||||
"praesent", "luctus", "lorem", "a", "mollis", "lacinia", "leo", "turpis", "commodo", "sem", "in", "lacinia", "mi",
|
||||
"quam", "et", "quam", "curabitur", "a", "libero", "vel", "tellus", "mattis", "imperdiet", "in", "congue", "neque", "ut",
|
||||
"scelerisque", "bibendum", "libero", "lacus", "ullamcorper", "sapien", "quis", "aliquet", "massa", "velit",
|
||||
"vel", "orci", "fusce", "in", "nulla", "quis", "est", "cursus", "gravida", "in", "nibh", "lorem", "ipsum", "dolor", "sit",
|
||||
"amet", "consectetuer", "adipiscing", "elit", "integer", "fermentum", "pretium", "massa", "morbi", "feugiat",
|
||||
"iaculis", "nunc", "aenean", "aliquam", "pretium", "orci", "cum", "sociis", "natoque", "penatibus", "et", "magnis",
|
||||
"dis", "parturient", "montes", "nascetur", "ridiculus", "mus", "vivamus", "quis", "tellus", "vel", "quam",
|
||||
"varius", "bibendum", "fusce", "est", "metus", "feugiat", "at", "porttitor", "et", "cursus", "quis", "pede", "nam", "ut",
|
||||
"augue", "nulla", "posuere", "phasellus", "at", "dolor", "a", "enim", "cursus", "vestibulum", "duis", "id", "nisi",
|
||||
"duis", "semper", "tellus", "ac", "nulla", "vestibulum", "scelerisque", "lobortis", "dolor", "aenean", "a",
|
||||
"felis", "aliquam", "erat", "volutpat", "donec", "a", "magna", "vitae", "pede", "sagittis", "lacinia", "cras",
|
||||
"vestibulum", "diam", "ut", "arcu", "mauris", "a", "nunc", "duis", "sollicitudin", "erat", "sit", "amet", "turpis",
|
||||
"proin", "at", "libero", "eu", "diam", "lobortis", "fermentum", "nunc", "lorem", "turpis", "imperdiet", "id",
|
||||
"gravida", "eget", "aliquet", "sed", "purus", "ut", "vehicula", "laoreet", "ante", "mauris", "eu", "nunc", "sed", "sit",
|
||||
"amet", "elit", "nec", "ipsum", "aliquam", "egestas", "donec", "non", "nibh", "cras", "sodales", "pretium", "massa",
|
||||
"praesent", "hendrerit", "est", "et", "risus", "vivamus", "eget", "pede", "curabitur", "tristique",
|
||||
"scelerisque", "dui", "nullam", "ullamcorper", "vivamus", "venenatis", "velit", "eget", "enim", "nunc", "eu",
|
||||
"nunc", "eget", "felis", "malesuada", "fermentum", "quisque", "magna", "mauris", "ligula", "felis", "luctus", "a",
|
||||
"aliquet", "nec", "vulputate", "eget", "magna", "quisque", "placerat", "diam", "sed", "arcu", "praesent",
|
||||
"sollicitudin", "aliquam", "non", "sapien", "quisque", "id", "augue", "class", "aptent", "taciti", "sociosqu",
|
||||
"ad", "litora", "torquent", "per", "conubia", "nostra", "per", "inceptos", "hymenaeos", "etiam", "lacus", "lectus",
|
||||
"mollis", "quis", "mattis", "nec", "commodo", "facilisis", "nibh", "sed", "sodales", "sapien", "ac", "ante", "duis",
|
||||
"eget", "lectus", "in", "nibh", "lacinia", "auctor", "fusce", "interdum", "lectus", "non", "dui", "integer",
|
||||
"accumsan", "quisque", "quam", "curabitur", "scelerisque", "imperdiet", "nisl", "suspendisse", "potenti",
|
||||
"nam", "massa", "leo", "iaculis", "sed", "accumsan", "id", "ultrices", "nec", "velit", "suspendisse", "potenti",
|
||||
"mauris", "bibendum", "turpis", "ac", "viverra", "sollicitudin", "metus", "massa", "interdum", "orci", "non",
|
||||
"imperdiet", "orci", "ante", "at", "ipsum", "etiam", "eget", "magna", "mauris", "at", "tortor", "eu", "lectus",
|
||||
"tempor", "tincidunt", "phasellus", "justo", "purus", "pharetra", "ut", "ultricies", "nec", "consequat", "vel",
|
||||
"nisi", "fusce", "vitae", "velit", "at", "libero", "sollicitudin", "sodales", "aenean", "mi", "libero", "ultrices",
|
||||
"id", "suscipit", "vitae", "dapibus", "eu", "metus", "aenean", "vestibulum", "nibh", "ac", "massa", "vivamus",
|
||||
"vestibulum", "libero", "vitae", "purus", "in", "hac", "habitasse", "platea", "dictumst", "curabitur",
|
||||
"blandit", "nunc", "non", "arcu", "ut", "nec", "nibh", "morbi", "quis", "leo", "vel", "magna", "commodo", "rhoncus",
|
||||
"donec", "congue", "leo", "eu", "lacus", "pellentesque", "at", "erat", "id", "mi", "consequat", "congue", "praesent",
|
||||
"a", "nisl", "ut", "diam", "interdum", "molestie", "fusce", "suscipit", "rhoncus", "sem", "donec", "pretium",
|
||||
"aliquam", "molestie", "vivamus", "et", "justo", "at", "augue", "aliquet", "dapibus", "pellentesque", "felis",
|
||||
"morbi", "semper", "in", "venenatis", "imperdiet", "neque", "donec", "auctor", "molestie", "augue", "nulla", "id",
|
||||
"arcu", "sit", "amet", "dui", "lacinia", "convallis", "proin", "tincidunt", "proin", "a", "ante", "nunc", "imperdiet",
|
||||
"augue", "nullam", "sit", "amet", "arcu", "quisque", "laoreet", "viverra", "felis", "lorem", "ipsum", "dolor", "sit",
|
||||
"amet", "consectetuer", "adipiscing", "elit", "in", "hac", "habitasse", "platea", "dictumst", "pellentesque",
|
||||
"habitant", "morbi", "tristique", "senectus", "et", "netus", "et", "malesuada", "fames", "ac", "turpis", "egestas",
|
||||
"class", "aptent", "taciti", "sociosqu", "ad", "litora", "torquent", "per", "conubia", "nostra", "per", "inceptos",
|
||||
"hymenaeos", "nullam", "nibh", "sapien", "volutpat", "ut", "placerat", "quis", "ornare", "at", "lorem", "class",
|
||||
"aptent", "taciti", "sociosqu", "ad", "litora", "torquent", "per", "conubia", "nostra", "per", "inceptos",
|
||||
"hymenaeos", "morbi", "dictum", "massa", "id", "libero", "ut", "neque", "phasellus", "tincidunt", "nibh", "ut",
|
||||
"tincidunt", "lacinia", "lacus", "nulla", "aliquam", "mi", "a", "interdum", "dui", "augue", "non", "pede", "duis",
|
||||
"nunc", "magna", "vulputate", "a", "porta", "at", "tincidunt", "a", "nulla", "praesent", "facilisis",
|
||||
"suspendisse", "sodales", "feugiat", "purus", "cras", "et", "justo", "a", "mauris", "mollis", "imperdiet", "morbi",
|
||||
"erat", "mi", "ultrices", "eget", "aliquam", "elementum", "iaculis", "id", "velit", "in", "scelerisque", "enim",
|
||||
"sit", "amet", "turpis", "sed", "aliquam", "odio", "nonummy", "ullamcorper", "mollis", "lacus", "nibh", "tempor",
|
||||
"dolor", "sit", "amet", "varius", "sem", "neque", "ac", "dui", "nunc", "et", "est", "eu", "massa", "eleifend", "mollis",
|
||||
"mauris", "aliquet", "orci", "quis", "tellus", "ut", "mattis", "praesent", "mollis", "consectetuer", "quam",
|
||||
"nulla", "nulla", "nunc", "accumsan", "nunc", "sit", "amet", "scelerisque", "porttitor", "nibh", "pede", "lacinia",
|
||||
"justo", "tristique", "mattis", "purus", "eros", "non", "velit", "aenean", "sagittis", "commodo", "erat",
|
||||
"aliquam", "id", "lacus", "morbi", "vulputate", "vestibulum", "elit",
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package tsm1_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
"testing/quick"
|
||||
|
@ -131,31 +132,44 @@ func Test_BooleanDecoder_Corrupt(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func BenchmarkBooleanDecoder_2048(b *testing.B) { benchmarkBooleanDecoder(b, 2048) }
|
||||
|
||||
func benchmarkBooleanDecoder(b *testing.B, size int) {
|
||||
e := tsm1.NewBooleanEncoder(size)
|
||||
for i := 0; i < size; i++ {
|
||||
e.Write(i&1 == 1)
|
||||
}
|
||||
bytes, err := e.Bytes()
|
||||
if err != nil {
|
||||
b.Fatalf("unexpected error: %v", err)
|
||||
func BenchmarkBooleanDecoder_DecodeAll(b *testing.B) {
|
||||
benchmarks := []struct {
|
||||
n int
|
||||
}{
|
||||
{1},
|
||||
{55},
|
||||
{555},
|
||||
{1000},
|
||||
}
|
||||
for _, bm := range benchmarks {
|
||||
b.Run(fmt.Sprintf("%d", bm.n), func(b *testing.B) {
|
||||
size := bm.n
|
||||
e := tsm1.NewBooleanEncoder(size)
|
||||
for i := 0; i < size; i++ {
|
||||
e.Write(i&1 == 1)
|
||||
}
|
||||
bytes, err := e.Bytes()
|
||||
if err != nil {
|
||||
b.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
b.SetBytes(int64(len(bytes)))
|
||||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
var d tsm1.BooleanDecoder
|
||||
d.SetBytes(bytes)
|
||||
dst := make([]bool, size)
|
||||
for i := 0; i < b.N; i++ {
|
||||
var d tsm1.BooleanDecoder
|
||||
d.SetBytes(bytes)
|
||||
|
||||
var n int
|
||||
for d.Next() {
|
||||
_ = d.Read()
|
||||
n++
|
||||
}
|
||||
if n != size {
|
||||
b.Fatalf("expected to read %d booleans, but read %d", size, n)
|
||||
}
|
||||
var n int
|
||||
for d.Next() {
|
||||
dst[n] = d.Read()
|
||||
n++
|
||||
}
|
||||
if n != size {
|
||||
b.Fatalf("expected to read %d booleans, but read %d", size, n)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package tsm1_test
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
@ -1470,6 +1471,175 @@ func BenchmarkDecodeBlock_Boolean_TypeSpecific(b *testing.B) {
|
|||
}
|
||||
}
|
||||
|
||||
func BenchmarkDecodeBooleanBlock(b *testing.B) {
|
||||
cases := []int{
|
||||
5,
|
||||
55,
|
||||
555,
|
||||
1000,
|
||||
}
|
||||
for _, n := range cases {
|
||||
b.Run(fmt.Sprintf("%d", n), func(b *testing.B) {
|
||||
valueCount := n
|
||||
times := getTimes(valueCount, 60, time.Second)
|
||||
values := make([]tsm1.Value, len(times))
|
||||
for i, t := range times {
|
||||
values[i] = tsm1.NewValue(t, true)
|
||||
}
|
||||
|
||||
bytes, err := tsm1.Values(values).Encode(nil)
|
||||
if err != nil {
|
||||
b.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
b.SetBytes(int64(tsm1.Values(values).Size()))
|
||||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
decodedValues := make([]tsm1.BooleanValue, len(values))
|
||||
|
||||
for pb.Next() {
|
||||
_, err = tsm1.DecodeBooleanBlock(bytes, &decodedValues)
|
||||
if err != nil {
|
||||
b.Fatalf("unexpected error decoding block: %v", err)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkDecodeFloatBlock(b *testing.B) {
|
||||
cases := []int{
|
||||
5,
|
||||
55,
|
||||
555,
|
||||
1000,
|
||||
}
|
||||
for _, n := range cases {
|
||||
b.Run(fmt.Sprintf("%d", n), func(b *testing.B) {
|
||||
valueCount := n
|
||||
times := getTimes(valueCount, 60, time.Second)
|
||||
values := make([]tsm1.Value, len(times))
|
||||
for i, t := range times {
|
||||
values[i] = tsm1.NewValue(t, float64(i))
|
||||
}
|
||||
|
||||
bytes, err := tsm1.Values(values).Encode(nil)
|
||||
if err != nil {
|
||||
b.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
b.SetBytes(int64(tsm1.Values(values).Size()))
|
||||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
decodedValues := make([]tsm1.FloatValue, len(values))
|
||||
|
||||
for pb.Next() {
|
||||
_, err = tsm1.DecodeFloatBlock(bytes, &decodedValues)
|
||||
if err != nil {
|
||||
b.Fatalf("unexpected error decoding block: %v", err)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkDecodeIntegerBlock(b *testing.B) {
|
||||
rle := func(i int) int64 { return int64(i) }
|
||||
s8b := func(i int) int64 { return int64(i + int(rand.Int31n(10))) }
|
||||
|
||||
cases := []struct {
|
||||
enc string
|
||||
gen func(i int) int64
|
||||
n int
|
||||
}{
|
||||
{enc: "rle", gen: rle, n: 5},
|
||||
{enc: "rle", gen: rle, n: 55},
|
||||
{enc: "rle", gen: rle, n: 555},
|
||||
{enc: "rle", gen: rle, n: 1000},
|
||||
{enc: "s8b", gen: s8b, n: 5},
|
||||
{enc: "s8b", gen: s8b, n: 55},
|
||||
{enc: "s8b", gen: s8b, n: 555},
|
||||
{enc: "s8b", gen: s8b, n: 1000},
|
||||
}
|
||||
for _, bm := range cases {
|
||||
b.Run(fmt.Sprintf("%s_%d", bm.enc, bm.n), func(b *testing.B) {
|
||||
rand.Seed(int64(bm.n * 1e3))
|
||||
|
||||
valueCount := bm.n
|
||||
times := getTimes(valueCount, 60, time.Second)
|
||||
values := make([]tsm1.Value, len(times))
|
||||
for i, t := range times {
|
||||
values[i] = tsm1.NewValue(t, bm.gen(i))
|
||||
}
|
||||
|
||||
bytes, err := tsm1.Values(values).Encode(nil)
|
||||
if err != nil {
|
||||
b.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
b.SetBytes(int64(tsm1.Values(values).Size()))
|
||||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
decodedValues := make([]tsm1.IntegerValue, len(values))
|
||||
|
||||
for pb.Next() {
|
||||
_, err = tsm1.DecodeIntegerBlock(bytes, &decodedValues)
|
||||
if err != nil {
|
||||
b.Fatalf("unexpected error decoding block: %v", err)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkDecodeStringBlock(b *testing.B) {
|
||||
cases := []int{
|
||||
5,
|
||||
55,
|
||||
555,
|
||||
1000,
|
||||
}
|
||||
for _, n := range cases {
|
||||
b.Run(fmt.Sprintf("%d", n), func(b *testing.B) {
|
||||
valueCount := n
|
||||
times := getTimes(valueCount, 60, time.Second)
|
||||
values := make([]tsm1.Value, len(times))
|
||||
for i, t := range times {
|
||||
values[i] = tsm1.NewValue(t, fmt.Sprintf("value %d", i))
|
||||
}
|
||||
|
||||
bytes, err := tsm1.Values(values).Encode(nil)
|
||||
if err != nil {
|
||||
b.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
b.SetBytes(int64(tsm1.Values(values).Size()))
|
||||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
decodedValues := make([]tsm1.StringValue, len(values))
|
||||
|
||||
for pb.Next() {
|
||||
_, err = tsm1.DecodeStringBlock(bytes, &decodedValues)
|
||||
if err != nil {
|
||||
b.Fatalf("unexpected error decoding block: %v", err)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkDecodeBlock_String_Empty(b *testing.B) {
|
||||
valueCount := 1000
|
||||
times := getTimes(valueCount, 60, time.Second)
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
package tsm1_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"reflect"
|
||||
"testing"
|
||||
"testing/quick"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/influxdata/influxdb/tsdb/engine/tsm1"
|
||||
)
|
||||
|
||||
|
@ -118,40 +120,26 @@ func TestFloatEncoder_SimilarFloats(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
var TwoHoursData = []struct {
|
||||
v float64
|
||||
}{
|
||||
// 2h of data
|
||||
{761}, {727}, {763}, {706}, {700},
|
||||
{679}, {757}, {708}, {739}, {707},
|
||||
{699}, {740}, {729}, {766}, {730},
|
||||
{715}, {705}, {693}, {765}, {724},
|
||||
{799}, {761}, {737}, {766}, {756},
|
||||
{719}, {722}, {801}, {747}, {731},
|
||||
{742}, {744}, {791}, {750}, {759},
|
||||
{809}, {751}, {705}, {770}, {792},
|
||||
{727}, {762}, {772}, {721}, {748},
|
||||
{753}, {744}, {716}, {776}, {659},
|
||||
{789}, {766}, {758}, {690}, {795},
|
||||
{770}, {758}, {723}, {767}, {765},
|
||||
{693}, {706}, {681}, {727}, {724},
|
||||
{780}, {678}, {696}, {758}, {740},
|
||||
{735}, {700}, {742}, {747}, {752},
|
||||
{734}, {743}, {732}, {746}, {770},
|
||||
{780}, {710}, {731}, {712}, {712},
|
||||
{741}, {770}, {770}, {754}, {718},
|
||||
{670}, {775}, {749}, {795}, {756},
|
||||
{741}, {787}, {721}, {745}, {782},
|
||||
{765}, {780}, {811}, {790}, {836},
|
||||
{743}, {858}, {739}, {762}, {770},
|
||||
{752}, {763}, {795}, {792}, {746},
|
||||
{786}, {785}, {774}, {786}, {718},
|
||||
var twoHoursData = []float64{
|
||||
// 2h of data, rows of 10 values
|
||||
761, 727, 763, 706, 700, 679, 757, 708, 739, 707,
|
||||
699, 740, 729, 766, 730, 715, 705, 693, 765, 724,
|
||||
799, 761, 737, 766, 756, 719, 722, 801, 747, 731,
|
||||
742, 744, 791, 750, 759, 809, 751, 705, 770, 792,
|
||||
727, 762, 772, 721, 748, 753, 744, 716, 776, 659,
|
||||
789, 766, 758, 690, 795, 770, 758, 723, 767, 765,
|
||||
693, 706, 681, 727, 724, 780, 678, 696, 758, 740,
|
||||
735, 700, 742, 747, 752, 734, 743, 732, 746, 770,
|
||||
780, 710, 731, 712, 712, 741, 770, 770, 754, 718,
|
||||
670, 775, 749, 795, 756, 741, 787, 721, 745, 782,
|
||||
765, 780, 811, 790, 836, 743, 858, 739, 762, 770,
|
||||
752, 763, 795, 792, 746, 786, 785, 774, 786, 718,
|
||||
}
|
||||
|
||||
func TestFloatEncoder_Roundtrip(t *testing.T) {
|
||||
s := tsm1.NewFloatEncoder()
|
||||
for _, p := range TwoHoursData {
|
||||
s.Write(p.v)
|
||||
for _, p := range twoHoursData {
|
||||
s.Write(p)
|
||||
}
|
||||
s.Flush()
|
||||
|
||||
|
@ -165,14 +153,14 @@ func TestFloatEncoder_Roundtrip(t *testing.T) {
|
|||
t.Fatalf("unexpected error creating float decoder: %v", err)
|
||||
}
|
||||
|
||||
for _, w := range TwoHoursData {
|
||||
for _, w := range twoHoursData {
|
||||
if !it.Next() {
|
||||
t.Fatalf("Next()=false, want true")
|
||||
}
|
||||
vv := it.Values()
|
||||
// t.Logf("it.Values()=(%+v, %+v)\n", time.Unix(int64(tt), 0), vv)
|
||||
if w.v != vv {
|
||||
t.Errorf("Values()=(%v), want (%v)\n", vv, w.v)
|
||||
if w != vv {
|
||||
t.Errorf("Values()=(%v), want (%v)\n", vv, w)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -253,8 +241,8 @@ func TestFloatDecoder_Empty(t *testing.T) {
|
|||
func BenchmarkFloatEncoder(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
s := tsm1.NewFloatEncoder()
|
||||
for _, tt := range TwoHoursData {
|
||||
s.Write(tt.v)
|
||||
for _, tt := range twoHoursData {
|
||||
s.Write(tt)
|
||||
}
|
||||
s.Flush()
|
||||
}
|
||||
|
@ -262,8 +250,8 @@ func BenchmarkFloatEncoder(b *testing.B) {
|
|||
|
||||
func BenchmarkFloatDecoder(b *testing.B) {
|
||||
s := tsm1.NewFloatEncoder()
|
||||
for _, tt := range TwoHoursData {
|
||||
s.Write(tt.v)
|
||||
for _, tt := range twoHoursData {
|
||||
s.Write(tt)
|
||||
}
|
||||
s.Flush()
|
||||
bytes, err := s.Bytes()
|
||||
|
@ -279,8 +267,53 @@ func BenchmarkFloatDecoder(b *testing.B) {
|
|||
b.Fatalf("unexpected error creating float decoder: %v", err)
|
||||
}
|
||||
|
||||
for j := 0; j < len(TwoHoursData); it.Next() {
|
||||
for j := 0; j < len(twoHoursData); it.Next() {
|
||||
j++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkFloatDecoder_DecodeAll(b *testing.B) {
|
||||
benchmarks := []struct {
|
||||
n int
|
||||
}{
|
||||
{1},
|
||||
{55},
|
||||
{550},
|
||||
{1000},
|
||||
}
|
||||
for _, bm := range benchmarks {
|
||||
b.Run(fmt.Sprintf("%d", bm.n), func(b *testing.B) {
|
||||
s := tsm1.NewFloatEncoder()
|
||||
for c := 0; c < bm.n; c++ {
|
||||
s.Write(twoHoursData[c%len(twoHoursData)])
|
||||
}
|
||||
s.Flush()
|
||||
bytes, err := s.Bytes()
|
||||
if err != nil {
|
||||
b.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
dst := make([]float64, bm.n)
|
||||
|
||||
b.SetBytes(int64(len(bytes)))
|
||||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
var it tsm1.FloatDecoder
|
||||
if err := it.SetBytes(bytes); err != nil {
|
||||
b.Fatalf("unexpected error creating float decoder: %v", err)
|
||||
}
|
||||
|
||||
i := 0
|
||||
for it.Next() {
|
||||
dst[i] = it.Values()
|
||||
i++
|
||||
}
|
||||
|
||||
if len(dst) != bm.n {
|
||||
b.Fatalf("unexpected length -got/+exp\n%s", cmp.Diff(len(dst), bm.n))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package tsm1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"math/rand"
|
||||
"reflect"
|
||||
|
@ -604,43 +605,130 @@ func BenchmarkIntegerEncoderPackedSimple(b *testing.B) {
|
|||
}
|
||||
}
|
||||
|
||||
func BenchmarkIntegerDecoderPackedSimple(b *testing.B) {
|
||||
x := make([]int64, 1024)
|
||||
enc := NewIntegerEncoder(1024)
|
||||
for i := 0; i < len(x); i++ {
|
||||
// Small amount of randomness prevents RLE from being used
|
||||
x[i] = int64(i) + int64(rand.Intn(10))
|
||||
enc.Write(x[i])
|
||||
func BenchmarkIntegerBatch_DecodeAllUncompressed(b *testing.B) {
|
||||
benchmarks := []struct {
|
||||
n int
|
||||
}{
|
||||
{5},
|
||||
{55},
|
||||
{555},
|
||||
{1000},
|
||||
}
|
||||
bytes, _ := enc.Bytes()
|
||||
|
||||
b.ResetTimer()
|
||||
values := []int64{
|
||||
-2352281900722994752, 1438442655375607923, -4110452567888190110,
|
||||
-1221292455668011702, -1941700286034261841, -2836753127140407751,
|
||||
1432686216250034552, 3663244026151507025, -3068113732684750258,
|
||||
-1949953187327444488, 3713374280993588804, 3226153669854871355,
|
||||
-2093273755080502606, 1006087192578600616, -2272122301622271655,
|
||||
2533238229511593671, -4450454445568858273, 2647789901083530435,
|
||||
2761419461769776844, -1324397441074946198, -680758138988210958,
|
||||
94468846694902125, -2394093124890745254, -2682139311758778198,
|
||||
}
|
||||
|
||||
var dec IntegerDecoder
|
||||
for i := 0; i < b.N; i++ {
|
||||
dec.SetBytes(bytes)
|
||||
for dec.Next() {
|
||||
}
|
||||
for _, bm := range benchmarks {
|
||||
b.Run(fmt.Sprintf("%d", bm.n), func(b *testing.B) {
|
||||
rand.Seed(int64(bm.n * 1e3))
|
||||
|
||||
enc := NewIntegerEncoder(bm.n)
|
||||
for i := 0; i < bm.n; i++ {
|
||||
enc.Write(values[rand.Int()%len(values)])
|
||||
}
|
||||
bytes, _ := enc.Bytes()
|
||||
|
||||
dst := make([]int64, bm.n)
|
||||
|
||||
b.SetBytes(int64(len(bytes)))
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
var dec IntegerDecoder
|
||||
dec.SetBytes(bytes)
|
||||
var n int
|
||||
for dec.Next() {
|
||||
dst[n] = dec.Read()
|
||||
n++
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIntegerDecoderRLE(b *testing.B) {
|
||||
x := make([]int64, 1024)
|
||||
enc := NewIntegerEncoder(1024)
|
||||
for i := 0; i < len(x); i++ {
|
||||
x[i] = int64(i)
|
||||
enc.Write(x[i])
|
||||
func BenchmarkIntegerBatch_DecodeAllPackedSimple(b *testing.B) {
|
||||
benchmarks := []struct {
|
||||
n int
|
||||
}{
|
||||
{5},
|
||||
{55},
|
||||
{555},
|
||||
{1000},
|
||||
}
|
||||
bytes, _ := enc.Bytes()
|
||||
for _, bm := range benchmarks {
|
||||
b.Run(fmt.Sprintf("%d", bm.n), func(b *testing.B) {
|
||||
rand.Seed(int64(bm.n * 1e3))
|
||||
|
||||
b.ResetTimer()
|
||||
enc := NewIntegerEncoder(bm.n)
|
||||
for i := 0; i < bm.n; i++ {
|
||||
// Small amount of randomness prevents RLE from being used
|
||||
enc.Write(int64(i) + int64(rand.Intn(10)))
|
||||
}
|
||||
bytes, _ := enc.Bytes()
|
||||
|
||||
var dec IntegerDecoder
|
||||
dec.SetBytes(bytes)
|
||||
dst := make([]int64, bm.n)
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
dec.SetBytes(bytes)
|
||||
for dec.Next() {
|
||||
}
|
||||
b.SetBytes(int64(len(bytes)))
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
var dec IntegerDecoder
|
||||
dec.SetBytes(bytes)
|
||||
var n int
|
||||
for dec.Next() {
|
||||
dst[n] = dec.Read()
|
||||
n++
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIntegerBatch_DecodeAllRLE(b *testing.B) {
|
||||
benchmarks := []struct {
|
||||
n int
|
||||
delta int64
|
||||
}{
|
||||
{5, 1},
|
||||
{55, 1},
|
||||
{555, 1},
|
||||
{1000, 1},
|
||||
{1000, 0},
|
||||
}
|
||||
for _, bm := range benchmarks {
|
||||
b.Run(fmt.Sprintf("%d_delta_%d", bm.n, bm.delta), func(b *testing.B) {
|
||||
enc := NewIntegerEncoder(bm.n)
|
||||
acc := int64(0)
|
||||
for i := 0; i < bm.n; i++ {
|
||||
enc.Write(acc)
|
||||
acc += bm.delta
|
||||
}
|
||||
bytes, _ := enc.Bytes()
|
||||
|
||||
b.SetBytes(int64(len(bytes)))
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
|
||||
dst := make([]int64, bm.n)
|
||||
for i := 0; i < b.N; i++ {
|
||||
var dec IntegerDecoder
|
||||
dec.SetBytes(bytes)
|
||||
var n int
|
||||
for dec.Next() {
|
||||
dst[n] = dec.Read()
|
||||
n++
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,9 +2,13 @@ package tsm1
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"reflect"
|
||||
"testing"
|
||||
"testing/quick"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/influxdata/influxdb/internal/testutil"
|
||||
)
|
||||
|
||||
func Test_StringEncoder_NoValues(t *testing.T) {
|
||||
|
@ -175,3 +179,52 @@ func Test_StringDecoder_CorruptSetBytes(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkStringDecoder_DecodeAll(b *testing.B) {
|
||||
benchmarks := []struct {
|
||||
n int
|
||||
w int
|
||||
}{
|
||||
{1, 10},
|
||||
{55, 10},
|
||||
{550, 10},
|
||||
{1000, 10},
|
||||
}
|
||||
for _, bm := range benchmarks {
|
||||
b.Run(fmt.Sprintf("%d", bm.n), func(b *testing.B) {
|
||||
rand.Seed(int64(bm.n * 1e3))
|
||||
|
||||
s := NewStringEncoder(bm.n)
|
||||
for c := 0; c < bm.n; c++ {
|
||||
s.Write(testutil.MakeSentence(bm.w))
|
||||
}
|
||||
s.Flush()
|
||||
bytes, err := s.Bytes()
|
||||
if err != nil {
|
||||
b.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
dst := make([]string, bm.n)
|
||||
|
||||
b.ReportAllocs()
|
||||
b.SetBytes(int64(len(bytes)))
|
||||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
var it StringDecoder
|
||||
if err := it.SetBytes(bytes); err != nil {
|
||||
b.Fatalf("unexpected error creating float decoder: %v", err)
|
||||
}
|
||||
|
||||
i := 0
|
||||
for it.Next() {
|
||||
dst[i] = it.Read()
|
||||
i++
|
||||
}
|
||||
|
||||
if len(dst) != bm.n {
|
||||
b.Fatalf("unexpected length -got/+exp\n%s", cmp.Diff(len(dst), bm.n))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package tsm1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"reflect"
|
||||
"testing"
|
||||
"testing/quick"
|
||||
|
@ -602,3 +604,131 @@ func BenchmarkTimeDecoder_RLE(b *testing.B) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkTimeBatch_DecodeAllUncompressed(b *testing.B) {
|
||||
benchmarks := []struct {
|
||||
n int
|
||||
}{
|
||||
{5},
|
||||
{55},
|
||||
{555},
|
||||
{1000},
|
||||
}
|
||||
|
||||
values := []int64{
|
||||
-2352281900722994752, 1438442655375607923, -4110452567888190110,
|
||||
-1221292455668011702, -1941700286034261841, -2836753127140407751,
|
||||
1432686216250034552, 3663244026151507025, -3068113732684750258,
|
||||
-1949953187327444488, 3713374280993588804, 3226153669854871355,
|
||||
-2093273755080502606, 1006087192578600616, -2272122301622271655,
|
||||
2533238229511593671, -4450454445568858273, 2647789901083530435,
|
||||
2761419461769776844, -1324397441074946198, -680758138988210958,
|
||||
94468846694902125, -2394093124890745254, -2682139311758778198,
|
||||
}
|
||||
|
||||
for _, bm := range benchmarks {
|
||||
b.Run(fmt.Sprintf("%d", bm.n), func(b *testing.B) {
|
||||
rand.Seed(int64(bm.n * 1e3))
|
||||
|
||||
enc := NewTimeEncoder(bm.n)
|
||||
for i := 0; i < bm.n; i++ {
|
||||
enc.Write(values[rand.Int()%len(values)])
|
||||
}
|
||||
bytes, _ := enc.Bytes()
|
||||
|
||||
dst := make([]int64, bm.n)
|
||||
|
||||
b.SetBytes(int64(len(bytes)))
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
var dec TimeDecoder
|
||||
dec.Init(bytes)
|
||||
var n int
|
||||
for dec.Next() {
|
||||
dst[n] = dec.Read()
|
||||
n++
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkTimeBatch_DecodeAllPackedSimple(b *testing.B) {
|
||||
benchmarks := []struct {
|
||||
n int
|
||||
}{
|
||||
{5},
|
||||
{55},
|
||||
{555},
|
||||
{1000},
|
||||
}
|
||||
for _, bm := range benchmarks {
|
||||
b.Run(fmt.Sprintf("%d", bm.n), func(b *testing.B) {
|
||||
rand.Seed(int64(bm.n * 1e3))
|
||||
|
||||
enc := NewTimeEncoder(bm.n)
|
||||
for i := 0; i < bm.n; i++ {
|
||||
// Small amount of randomness prevents RLE from being used
|
||||
enc.Write(int64(i*1000) + int64(rand.Intn(10)))
|
||||
}
|
||||
bytes, _ := enc.Bytes()
|
||||
|
||||
dst := make([]int64, bm.n)
|
||||
|
||||
b.SetBytes(int64(len(bytes)))
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
var dec TimeDecoder
|
||||
dec.Init(bytes)
|
||||
var n int
|
||||
for dec.Next() {
|
||||
dst[n] = dec.Read()
|
||||
n++
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkTimeBatch_DecodeAllRLE(b *testing.B) {
|
||||
benchmarks := []struct {
|
||||
n int
|
||||
delta int64
|
||||
}{
|
||||
{5, 10},
|
||||
{55, 10},
|
||||
{555, 10},
|
||||
{1000, 10},
|
||||
}
|
||||
for _, bm := range benchmarks {
|
||||
b.Run(fmt.Sprintf("%d_delta_%d", bm.n, bm.delta), func(b *testing.B) {
|
||||
enc := NewTimeEncoder(bm.n)
|
||||
acc := int64(0)
|
||||
for i := 0; i < bm.n; i++ {
|
||||
enc.Write(acc)
|
||||
acc += bm.delta
|
||||
}
|
||||
bytes, _ := enc.Bytes()
|
||||
|
||||
dst := make([]int64, bm.n)
|
||||
|
||||
b.SetBytes(int64(len(bytes)))
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
var dec TimeDecoder
|
||||
dec.Init(bytes)
|
||||
var n int
|
||||
for dec.Next() {
|
||||
dst[n] = dec.Read()
|
||||
n++
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue