package tsm1_test import ( "fmt" "math/rand" "reflect" "testing" "time" "github.com/davecgh/go-spew/spew" "github.com/influxdata/platform/tsdb/tsm1" ) func TestEncoding_FloatBlock(t *testing.T) { valueCount := 1000 times := getTimes(valueCount, 60, time.Second) values := make([]tsm1.Value, len(times)) for i, t := range times { values[i] = tsm1.NewValue(t, float64(i)) } b, err := tsm1.Values(values).Encode(nil) if err != nil { t.Fatalf("unexpected error: %v", err) } var decodedValues []tsm1.Value decodedValues, err = tsm1.DecodeBlock(b, decodedValues) if err != nil { t.Fatalf("unexpected error decoding block: %v", err) } if !reflect.DeepEqual(decodedValues, values) { t.Fatalf("unexpected results:\n\tgot: %s\n\texp: %s\n", spew.Sdump(decodedValues), spew.Sdump(values)) } } func TestEncoding_FloatBlock_ZeroTime(t *testing.T) { values := make([]tsm1.Value, 3) for i := 0; i < 3; i++ { values[i] = tsm1.NewValue(0, float64(i)) } b, err := tsm1.Values(values).Encode(nil) if err != nil { t.Fatalf("unexpected error: %v", err) } var decodedValues []tsm1.Value decodedValues, err = tsm1.DecodeBlock(b, decodedValues) if err != nil { t.Fatalf("unexpected error decoding block: %v", err) } if !reflect.DeepEqual(decodedValues, values) { t.Fatalf("unexpected results:\n\tgot: %v\n\texp: %v\n", decodedValues, values) } } func TestEncoding_FloatBlock_SimilarFloats(t *testing.T) { values := make([]tsm1.Value, 5) values[0] = tsm1.NewValue(1444238178437870000, 6.00065e+06) values[1] = tsm1.NewValue(1444238185286830000, 6.000656e+06) values[2] = tsm1.NewValue(1444238188441501000, 6.000657e+06) values[3] = tsm1.NewValue(1444238195286811000, 6.000659e+06) values[4] = tsm1.NewValue(1444238198439917000, 6.000661e+06) b, err := tsm1.Values(values).Encode(nil) if err != nil { t.Fatalf("unexpected error: %v", err) } var decodedValues []tsm1.Value decodedValues, err = tsm1.DecodeBlock(b, decodedValues) if err != nil { t.Fatalf("unexpected error decoding block: %v", err) } if !reflect.DeepEqual(decodedValues, values) { t.Fatalf("unexpected results:\n\tgot: %v\n\texp: %v\n", decodedValues, values) } } func TestEncoding_IntBlock_Basic(t *testing.T) { valueCount := 1000 times := getTimes(valueCount, 60, time.Second) values := make([]tsm1.Value, len(times)) for i, t := range times { values[i] = tsm1.NewValue(t, int64(i)) } b, err := tsm1.Values(values).Encode(nil) if err != nil { t.Fatalf("unexpected error: %v", err) } var decodedValues []tsm1.Value decodedValues, err = tsm1.DecodeBlock(b, decodedValues) if err != nil { t.Fatalf("unexpected error decoding block: %v", err) } if len(decodedValues) != len(values) { t.Fatalf("unexpected results length:\n\tgot: %v\n\texp: %v\n", len(decodedValues), len(values)) } for i := 0; i < len(decodedValues); i++ { if decodedValues[i].UnixNano() != values[i].UnixNano() { t.Fatalf("unexpected results:\n\tgot: %v\n\texp: %v\n", decodedValues[i].UnixNano(), values[i].UnixNano()) } if decodedValues[i].Value() != values[i].Value() { t.Fatalf("unexpected results:\n\tgot: %v\n\texp: %v\n", decodedValues[i].Value(), values[i].Value()) } } } func TestEncoding_IntBlock_Negatives(t *testing.T) { valueCount := 1000 times := getTimes(valueCount, 60, time.Second) values := make([]tsm1.Value, len(times)) for i, t := range times { v := int64(i) if i%2 == 0 { v = -v } values[i] = tsm1.NewValue(t, int64(v)) } b, err := tsm1.Values(values).Encode(nil) if err != nil { t.Fatalf("unexpected error: %v", err) } var decodedValues []tsm1.Value decodedValues, err = tsm1.DecodeBlock(b, decodedValues) if err != nil { t.Fatalf("unexpected error decoding block: %v", err) } if !reflect.DeepEqual(decodedValues, values) { t.Fatalf("unexpected results:\n\tgot: %v\n\texp: %v\n", decodedValues, values) } } func TestEncoding_UIntBlock_Basic(t *testing.T) { valueCount := 1000 times := getTimes(valueCount, 60, time.Second) values := make([]tsm1.Value, len(times)) for i, t := range times { values[i] = tsm1.NewValue(t, uint64(i)) } b, err := tsm1.Values(values).Encode(nil) if err != nil { t.Fatalf("unexpected error: %v", err) } var decodedValues []tsm1.Value decodedValues, err = tsm1.DecodeBlock(b, decodedValues) if err != nil { t.Fatalf("unexpected error decoding block: %v", err) } if len(decodedValues) != len(values) { t.Fatalf("unexpected results length:\n\tgot: %v\n\texp: %v\n", len(decodedValues), len(values)) } for i := 0; i < len(decodedValues); i++ { if decodedValues[i].UnixNano() != values[i].UnixNano() { t.Fatalf("unexpected results:\n\tgot: %v\n\texp: %v\n", decodedValues[i].UnixNano(), values[i].UnixNano()) } if decodedValues[i].Value() != values[i].Value() { t.Fatalf("unexpected results:\n\tgot: %v\n\texp: %v\n", decodedValues[i].Value(), values[i].Value()) } } } // TestEncoding_UIntBlock_MaxValues encodes uint64 numbers starting at max (18446744073709551615) // down to 18446744073709550616 func TestEncoding_UIntBlock_MaxValues(t *testing.T) { valueCount := 1000 times := getTimes(valueCount, 60, time.Second) values := make([]tsm1.Value, len(times)) for i, t := range times { values[i] = tsm1.NewValue(t, ^uint64(i)) } b, err := tsm1.Values(values).Encode(nil) if err != nil { t.Fatalf("unexpected error: %v", err) } var decodedValues []tsm1.Value decodedValues, err = tsm1.DecodeBlock(b, decodedValues) if err != nil { t.Fatalf("unexpected error decoding block: %v", err) } if !reflect.DeepEqual(decodedValues, values) { t.Fatalf("unexpected results:\n\tgot: %v\n\texp: %v\n", decodedValues, values) } } func TestEncoding_BooleanBlock_Basic(t *testing.T) { valueCount := 1000 times := getTimes(valueCount, 60, time.Second) values := make([]tsm1.Value, len(times)) for i, t := range times { v := true if i%2 == 0 { v = false } values[i] = tsm1.NewValue(t, v) } b, err := tsm1.Values(values).Encode(nil) if err != nil { t.Fatalf("unexpected error: %v", err) } var decodedValues []tsm1.Value decodedValues, err = tsm1.DecodeBlock(b, decodedValues) if err != nil { t.Fatalf("unexpected error decoding block: %v", err) } if !reflect.DeepEqual(decodedValues, values) { t.Fatalf("unexpected results:\n\tgot: %v\n\texp: %v\n", decodedValues, values) } } func TestEncoding_StringBlock_Basic(t *testing.T) { valueCount := 1000 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)) } b, err := tsm1.Values(values).Encode(nil) if err != nil { t.Fatalf("unexpected error: %v", err) } var decodedValues []tsm1.Value decodedValues, err = tsm1.DecodeBlock(b, decodedValues) if err != nil { t.Fatalf("unexpected error decoding block: %v", err) } if !reflect.DeepEqual(decodedValues, values) { t.Fatalf("unexpected results:\n\tgot: %v\n\texp: %v\n", decodedValues, values) } } func TestEncoding_BlockType(t *testing.T) { tests := []struct { value interface{} blockType byte }{ {value: float64(1.0), blockType: tsm1.BlockFloat64}, {value: int64(1), blockType: tsm1.BlockInteger}, {value: uint64(1), blockType: tsm1.BlockUnsigned}, {value: true, blockType: tsm1.BlockBoolean}, {value: "string", blockType: tsm1.BlockString}, } for _, test := range tests { var values []tsm1.Value values = append(values, tsm1.NewValue(0, test.value)) b, err := tsm1.Values(values).Encode(nil) if err != nil { t.Fatalf("unexpected error: %v", err) } bt, err := tsm1.BlockType(b) if err != nil { t.Fatalf("unexpected error decoding block type: %v", err) } if got, exp := bt, test.blockType; got != exp { t.Fatalf("block type mismatch: got %v, exp %v", got, exp) } } _, err := tsm1.BlockType([]byte{10}) if err == nil { t.Fatalf("expected error decoding block type, got nil") } } func TestEncoding_Count(t *testing.T) { tests := []struct { value interface{} blockType byte }{ {value: float64(1.0), blockType: tsm1.BlockFloat64}, {value: int64(1), blockType: tsm1.BlockInteger}, {value: uint64(1), blockType: tsm1.BlockUnsigned}, {value: true, blockType: tsm1.BlockBoolean}, {value: "string", blockType: tsm1.BlockString}, } for _, test := range tests { var values []tsm1.Value values = append(values, tsm1.NewValue(0, test.value)) b, err := tsm1.Values(values).Encode(nil) if err != nil { t.Fatalf("unexpected error: %v", err) } if got, exp := tsm1.BlockCount(b), 1; got != exp { t.Fatalf("block count mismatch: got %v, exp %v", got, exp) } } } func TestValues_MergeFloat(t *testing.T) { tests := []struct { a, b, exp []tsm1.Value }{ { // empty a a: []tsm1.Value{}, b: []tsm1.Value{ tsm1.NewValue(1, 1.2), tsm1.NewValue(2, 2.2), }, exp: []tsm1.Value{ tsm1.NewValue(1, 1.2), tsm1.NewValue(2, 2.2), }, }, { // empty b a: []tsm1.Value{ tsm1.NewValue(1, 1.1), tsm1.NewValue(2, 2.1), }, b: []tsm1.Value{}, exp: []tsm1.Value{ tsm1.NewValue(1, 1.1), tsm1.NewValue(2, 2.1), }, }, { a: []tsm1.Value{ tsm1.NewValue(0, 0.0), tsm1.NewValue(1, 1.1), tsm1.NewValue(2, 2.1), }, b: []tsm1.Value{ tsm1.NewValue(2, 2.2), tsm1.NewValue(2, 2.2), // duplicate data }, exp: []tsm1.Value{ tsm1.NewValue(0, 0.0), tsm1.NewValue(1, 1.1), tsm1.NewValue(2, 2.2), }, }, { a: []tsm1.Value{ tsm1.NewValue(0, 0.0), tsm1.NewValue(1, 1.1), tsm1.NewValue(1, 1.1), // duplicate data tsm1.NewValue(2, 2.1), }, b: []tsm1.Value{ tsm1.NewValue(2, 2.2), tsm1.NewValue(2, 2.2), // duplicate data }, exp: []tsm1.Value{ tsm1.NewValue(0, 0.0), tsm1.NewValue(1, 1.1), tsm1.NewValue(2, 2.2), }, }, { a: []tsm1.Value{ tsm1.NewValue(1, 1.1), }, b: []tsm1.Value{ tsm1.NewValue(0, 0.0), tsm1.NewValue(1, 1.2), // overwrites a tsm1.NewValue(2, 2.2), tsm1.NewValue(3, 3.2), tsm1.NewValue(4, 4.2), }, exp: []tsm1.Value{ tsm1.NewValue(0, 0.0), tsm1.NewValue(1, 1.2), tsm1.NewValue(2, 2.2), tsm1.NewValue(3, 3.2), tsm1.NewValue(4, 4.2), }, }, { a: []tsm1.Value{ tsm1.NewValue(1, 1.1), tsm1.NewValue(2, 2.1), tsm1.NewValue(3, 3.1), tsm1.NewValue(4, 4.1), }, b: []tsm1.Value{ tsm1.NewValue(1, 1.2), // overwrites a tsm1.NewValue(2, 2.2), // overwrites a }, exp: []tsm1.Value{ tsm1.NewValue(1, 1.2), tsm1.NewValue(2, 2.2), tsm1.NewValue(3, 3.1), tsm1.NewValue(4, 4.1), }, }, { a: []tsm1.Value{ tsm1.NewValue(1, 1.1), tsm1.NewValue(2, 2.1), tsm1.NewValue(3, 3.1), tsm1.NewValue(4, 4.1), }, b: []tsm1.Value{ tsm1.NewValue(1, 1.2), // overwrites a tsm1.NewValue(2, 2.2), // overwrites a tsm1.NewValue(3, 3.2), tsm1.NewValue(4, 4.2), }, exp: []tsm1.Value{ tsm1.NewValue(1, 1.2), tsm1.NewValue(2, 2.2), tsm1.NewValue(3, 3.2), tsm1.NewValue(4, 4.2), }, }, { a: []tsm1.Value{ tsm1.NewValue(0, 0.0), tsm1.NewValue(1, 1.1), tsm1.NewValue(2, 2.1), tsm1.NewValue(3, 3.1), tsm1.NewValue(4, 4.1), }, b: []tsm1.Value{ tsm1.NewValue(0, 0.0), tsm1.NewValue(2, 2.2), tsm1.NewValue(4, 4.2), }, exp: []tsm1.Value{ tsm1.NewValue(0, 0.0), tsm1.NewValue(1, 1.1), tsm1.NewValue(2, 2.2), tsm1.NewValue(3, 3.1), tsm1.NewValue(4, 4.2), }, }, { a: []tsm1.Value{ tsm1.NewValue(1462498658242869207, 0.0), tsm1.NewValue(1462498658288956853, 1.1), }, b: []tsm1.Value{ tsm1.NewValue(1462498658242870810, 0.0), tsm1.NewValue(1462498658262911238, 2.2), tsm1.NewValue(1462498658282415038, 4.2), tsm1.NewValue(1462498658282417760, 4.2), }, exp: []tsm1.Value{ tsm1.NewValue(1462498658242869207, 0.0), tsm1.NewValue(1462498658242870810, 0.0), tsm1.NewValue(1462498658262911238, 2.2), tsm1.NewValue(1462498658282415038, 4.2), tsm1.NewValue(1462498658282417760, 4.2), tsm1.NewValue(1462498658288956853, 1.1), }, }, { a: []tsm1.Value{ tsm1.NewValue(4, 4.0), tsm1.NewValue(5, 5.0), tsm1.NewValue(6, 6.0), }, b: []tsm1.Value{ tsm1.NewValue(1, 1.0), tsm1.NewValue(2, 2.0), tsm1.NewValue(3, 3.0), }, exp: []tsm1.Value{ tsm1.NewValue(1, 1.0), tsm1.NewValue(2, 2.0), tsm1.NewValue(3, 3.0), tsm1.NewValue(4, 4.0), tsm1.NewValue(5, 5.0), tsm1.NewValue(6, 6.0), }, }, { a: []tsm1.Value{ tsm1.NewValue(5, 5.0), tsm1.NewValue(6, 6.0), }, b: []tsm1.Value{ tsm1.NewValue(1, 1.0), tsm1.NewValue(2, 2.0), tsm1.NewValue(3, 3.0), tsm1.NewValue(4, 4.0), tsm1.NewValue(7, 7.0), tsm1.NewValue(8, 8.0), }, exp: []tsm1.Value{ tsm1.NewValue(1, 1.0), tsm1.NewValue(2, 2.0), tsm1.NewValue(3, 3.0), tsm1.NewValue(4, 4.0), tsm1.NewValue(5, 5.0), tsm1.NewValue(6, 6.0), tsm1.NewValue(7, 7.0), tsm1.NewValue(8, 8.0), }, }, { a: []tsm1.Value{ tsm1.NewValue(1, 1.0), tsm1.NewValue(2, 2.0), tsm1.NewValue(3, 3.0), }, b: []tsm1.Value{ tsm1.NewValue(4, 4.0), tsm1.NewValue(5, 5.0), tsm1.NewValue(6, 6.0), }, exp: []tsm1.Value{ tsm1.NewValue(1, 1.0), tsm1.NewValue(2, 2.0), tsm1.NewValue(3, 3.0), tsm1.NewValue(4, 4.0), tsm1.NewValue(5, 5.0), tsm1.NewValue(6, 6.0), }, }, } for i, test := range tests { got := tsm1.Values(test.a).Merge(test.b) if exp, got := len(test.exp), len(got); exp != got { t.Fatalf("test(%d): value length mismatch: exp %v, got %v", i, exp, got) } dedup := tsm1.Values(append(test.a, test.b...)).Deduplicate() for i := range test.exp { if exp, got := test.exp[i].String(), got[i].String(); exp != got { t.Fatalf("value mismatch:\n exp %v\n got %v", exp, got) } if exp, got := test.exp[i].String(), dedup[i].String(); exp != got { t.Fatalf("value mismatch:\n exp %v\n got %v", exp, got) } } } } func TestIntegerValues_Merge(t *testing.T) { integerValue := func(t int64, f int64) tsm1.IntegerValue { return tsm1.NewValue(t, f).(tsm1.IntegerValue) } tests := []struct { a, b, exp []tsm1.IntegerValue }{ { // empty a a: []tsm1.IntegerValue{}, b: []tsm1.IntegerValue{ integerValue(1, 10), integerValue(2, 20), }, exp: []tsm1.IntegerValue{ integerValue(1, 10), integerValue(2, 20), }, }, { // empty b a: []tsm1.IntegerValue{ integerValue(1, 1), integerValue(2, 2), }, b: []tsm1.IntegerValue{}, exp: []tsm1.IntegerValue{ integerValue(1, 1), integerValue(2, 2), }, }, { a: []tsm1.IntegerValue{ integerValue(1, 1), }, b: []tsm1.IntegerValue{ integerValue(0, 0), integerValue(1, 10), // overwrites a integerValue(2, 20), integerValue(3, 30), integerValue(4, 40), }, exp: []tsm1.IntegerValue{ integerValue(0, 0), integerValue(1, 10), integerValue(2, 20), integerValue(3, 30), integerValue(4, 40), }, }, { a: []tsm1.IntegerValue{ integerValue(1, 1), integerValue(2, 2), integerValue(3, 3), integerValue(4, 4), }, b: []tsm1.IntegerValue{ integerValue(1, 10), // overwrites a integerValue(2, 20), // overwrites a }, exp: []tsm1.IntegerValue{ integerValue(1, 10), integerValue(2, 20), integerValue(3, 3), integerValue(4, 4), }, }, { a: []tsm1.IntegerValue{ integerValue(1, 1), integerValue(2, 2), integerValue(3, 3), integerValue(4, 4), }, b: []tsm1.IntegerValue{ integerValue(1, 10), // overwrites a integerValue(2, 20), // overwrites a integerValue(3, 30), integerValue(4, 40), }, exp: []tsm1.IntegerValue{ integerValue(1, 10), integerValue(2, 20), integerValue(3, 30), integerValue(4, 40), }, }, { a: []tsm1.IntegerValue{ integerValue(0, 0), integerValue(1, 1), integerValue(2, 2), integerValue(3, 3), integerValue(4, 4), }, b: []tsm1.IntegerValue{ integerValue(0, 0), integerValue(2, 20), integerValue(4, 40), }, exp: []tsm1.IntegerValue{ integerValue(0, 0.0), integerValue(1, 1), integerValue(2, 20), integerValue(3, 3), integerValue(4, 40), }, }, } for i, test := range tests { if i != 2 { continue } got := tsm1.IntegerValues(test.a).Merge(test.b) if exp, got := len(test.exp), len(got); exp != got { t.Fatalf("test(%d): value length mismatch: exp %v, got %v", i, exp, got) } dedup := tsm1.IntegerValues(append(test.a, test.b...)).Deduplicate() for i := range test.exp { if exp, got := test.exp[i].String(), got[i].String(); exp != got { t.Fatalf("value mismatch:\n exp %v\n got %v", exp, got) } if exp, got := test.exp[i].String(), dedup[i].String(); exp != got { t.Fatalf("value mismatch:\n exp %v\n got %v", exp, got) } } } } func TestUnsignedValues_Merge(t *testing.T) { uintValue := func(t int64, f uint64) tsm1.UnsignedValue { return tsm1.NewValue(t, f).(tsm1.UnsignedValue) } tests := []struct { a, b, exp []tsm1.UnsignedValue }{ { // empty a a: []tsm1.UnsignedValue{}, b: []tsm1.UnsignedValue{ uintValue(1, 10), uintValue(2, 20), }, exp: []tsm1.UnsignedValue{ uintValue(1, 10), uintValue(2, 20), }, }, { // empty b a: []tsm1.UnsignedValue{ uintValue(1, 1), uintValue(2, 2), }, b: []tsm1.UnsignedValue{}, exp: []tsm1.UnsignedValue{ uintValue(1, 1), uintValue(2, 2), }, }, { a: []tsm1.UnsignedValue{ uintValue(1, 1), }, b: []tsm1.UnsignedValue{ uintValue(0, 0), uintValue(1, 10), // overwrites a uintValue(2, 20), uintValue(3, 30), uintValue(4, 40), }, exp: []tsm1.UnsignedValue{ uintValue(0, 0), uintValue(1, 10), uintValue(2, 20), uintValue(3, 30), uintValue(4, 40), }, }, { a: []tsm1.UnsignedValue{ uintValue(1, 1), uintValue(2, 2), uintValue(3, 3), uintValue(4, 4), }, b: []tsm1.UnsignedValue{ uintValue(1, ^uint64(0)), // overwrites a uintValue(2, 20), // overwrites a }, exp: []tsm1.UnsignedValue{ uintValue(1, ^uint64(0)), uintValue(2, 20), uintValue(3, 3), uintValue(4, 4), }, }, { a: []tsm1.UnsignedValue{ uintValue(1, 1), uintValue(2, 2), uintValue(3, 3), uintValue(4, 4), }, b: []tsm1.UnsignedValue{ uintValue(1, 10), // overwrites a uintValue(2, 20), // overwrites a uintValue(3, 30), uintValue(4, 40), }, exp: []tsm1.UnsignedValue{ uintValue(1, 10), uintValue(2, 20), uintValue(3, 30), uintValue(4, 40), }, }, { a: []tsm1.UnsignedValue{ uintValue(0, 0), uintValue(1, 1), uintValue(2, 2), uintValue(3, 3), uintValue(4, 4), }, b: []tsm1.UnsignedValue{ uintValue(0, 0), uintValue(2, 20), uintValue(4, 40), }, exp: []tsm1.UnsignedValue{ uintValue(0, 0.0), uintValue(1, 1), uintValue(2, 20), uintValue(3, 3), uintValue(4, 40), }, }, } for i, test := range tests { if i != 2 { continue } got := tsm1.UnsignedValues(test.a).Merge(test.b) if exp, got := len(test.exp), len(got); exp != got { t.Fatalf("test(%d): value length mismatch: exp %v, got %v", i, exp, got) } dedup := tsm1.UnsignedValues(append(test.a, test.b...)).Deduplicate() for i := range test.exp { if exp, got := test.exp[i].String(), got[i].String(); exp != got { t.Fatalf("value mismatch:\n exp %v\n got %v", exp, got) } if exp, got := test.exp[i].String(), dedup[i].String(); exp != got { t.Fatalf("value mismatch:\n exp %v\n got %v", exp, got) } } } } func TestFloatValues_Merge(t *testing.T) { floatValue := func(t int64, f float64) tsm1.FloatValue { return tsm1.NewValue(t, f).(tsm1.FloatValue) } tests := []struct { a, b, exp []tsm1.FloatValue }{ { // empty a a: []tsm1.FloatValue{}, b: []tsm1.FloatValue{ floatValue(1, 1.2), floatValue(2, 2.2), }, exp: []tsm1.FloatValue{ floatValue(1, 1.2), floatValue(2, 2.2), }, }, { // empty b a: []tsm1.FloatValue{ floatValue(1, 1.1), floatValue(2, 2.1), }, b: []tsm1.FloatValue{}, exp: []tsm1.FloatValue{ floatValue(1, 1.1), floatValue(2, 2.1), }, }, { a: []tsm1.FloatValue{ floatValue(1, 1.1), }, b: []tsm1.FloatValue{ floatValue(0, 0.0), floatValue(1, 1.2), // overwrites a floatValue(2, 2.2), floatValue(3, 3.2), floatValue(4, 4.2), }, exp: []tsm1.FloatValue{ floatValue(0, 0.0), floatValue(1, 1.2), floatValue(2, 2.2), floatValue(3, 3.2), floatValue(4, 4.2), }, }, { a: []tsm1.FloatValue{ floatValue(1, 1.1), floatValue(2, 2.1), floatValue(3, 3.1), floatValue(4, 4.1), }, b: []tsm1.FloatValue{ floatValue(1, 1.2), // overwrites a floatValue(2, 2.2), // overwrites a }, exp: []tsm1.FloatValue{ floatValue(1, 1.2), floatValue(2, 2.2), floatValue(3, 3.1), floatValue(4, 4.1), }, }, { a: []tsm1.FloatValue{ floatValue(1, 1.1), floatValue(2, 2.1), floatValue(3, 3.1), floatValue(4, 4.1), }, b: []tsm1.FloatValue{ floatValue(1, 1.2), // overwrites a floatValue(2, 2.2), // overwrites a floatValue(3, 3.2), floatValue(4, 4.2), }, exp: []tsm1.FloatValue{ floatValue(1, 1.2), floatValue(2, 2.2), floatValue(3, 3.2), floatValue(4, 4.2), }, }, { a: []tsm1.FloatValue{ floatValue(0, 0.0), floatValue(1, 1.1), floatValue(2, 2.1), floatValue(3, 3.1), floatValue(4, 4.1), }, b: []tsm1.FloatValue{ floatValue(0, 0.0), floatValue(2, 2.2), floatValue(4, 4.2), }, exp: []tsm1.FloatValue{ floatValue(0, 0.0), floatValue(1, 1.1), floatValue(2, 2.2), floatValue(3, 3.1), floatValue(4, 4.2), }, }, } for i, test := range tests { got := tsm1.FloatValues(test.a).Merge(test.b) if exp, got := len(test.exp), len(got); exp != got { t.Fatalf("test(%d): value length mismatch: exp %v, got %v", i, exp, got) } dedup := tsm1.FloatValues(append(test.a, test.b...)).Deduplicate() for i := range test.exp { if exp, got := test.exp[i].String(), got[i].String(); exp != got { t.Fatalf("value mismatch:\n exp %v\n got %v", exp, got) } if exp, got := test.exp[i].String(), dedup[i].String(); exp != got { t.Fatalf("value mismatch:\n exp %v\n got %v", exp, got) } } } } func TestBooleanValues_Merge(t *testing.T) { booleanValue := func(t int64, f bool) tsm1.BooleanValue { return tsm1.NewValue(t, f).(tsm1.BooleanValue) } tests := []struct { a, b, exp []tsm1.BooleanValue }{ { // empty a a: []tsm1.BooleanValue{}, b: []tsm1.BooleanValue{ booleanValue(1, true), booleanValue(2, true), }, exp: []tsm1.BooleanValue{ booleanValue(1, true), booleanValue(2, true), }, }, { // empty b a: []tsm1.BooleanValue{ booleanValue(1, true), booleanValue(2, true), }, b: []tsm1.BooleanValue{}, exp: []tsm1.BooleanValue{ booleanValue(1, true), booleanValue(2, true), }, }, { a: []tsm1.BooleanValue{ booleanValue(1, true), }, b: []tsm1.BooleanValue{ booleanValue(0, false), booleanValue(1, false), // overwrites a booleanValue(2, false), booleanValue(3, false), booleanValue(4, false), }, exp: []tsm1.BooleanValue{ booleanValue(0, false), booleanValue(1, false), booleanValue(2, false), booleanValue(3, false), booleanValue(4, false), }, }, { a: []tsm1.BooleanValue{ booleanValue(1, true), booleanValue(2, true), booleanValue(3, true), booleanValue(4, true), }, b: []tsm1.BooleanValue{ booleanValue(1, false), // overwrites a booleanValue(2, false), // overwrites a }, exp: []tsm1.BooleanValue{ booleanValue(1, false), // overwrites a booleanValue(2, false), // overwrites a booleanValue(3, true), booleanValue(4, true), }, }, { a: []tsm1.BooleanValue{ booleanValue(1, true), booleanValue(2, true), booleanValue(3, true), booleanValue(4, true), }, b: []tsm1.BooleanValue{ booleanValue(1, false), // overwrites a booleanValue(2, false), // overwrites a booleanValue(3, false), booleanValue(4, false), }, exp: []tsm1.BooleanValue{ booleanValue(1, false), booleanValue(2, false), booleanValue(3, false), booleanValue(4, false), }, }, { a: []tsm1.BooleanValue{ booleanValue(0, true), booleanValue(1, true), booleanValue(2, true), booleanValue(3, true), booleanValue(4, true), }, b: []tsm1.BooleanValue{ booleanValue(0, false), booleanValue(2, false), booleanValue(4, false), }, exp: []tsm1.BooleanValue{ booleanValue(0, false), booleanValue(1, true), booleanValue(2, false), booleanValue(3, true), booleanValue(4, false), }, }, } for i, test := range tests { got := tsm1.BooleanValues(test.a).Merge(test.b) if exp, got := len(test.exp), len(got); exp != got { t.Fatalf("test(%d): value length mismatch: exp %v, got %v", i, exp, got) } dedup := tsm1.BooleanValues(append(test.a, test.b...)).Deduplicate() for i := range test.exp { if exp, got := test.exp[i].String(), got[i].String(); exp != got { t.Fatalf("value mismatch:\n exp %v\n got %v", exp, got) } if exp, got := test.exp[i].String(), dedup[i].String(); exp != got { t.Fatalf("value mismatch:\n exp %v\n got %v", exp, got) } } } } func TestStringValues_Merge(t *testing.T) { stringValue := func(t int64, f string) tsm1.StringValue { return tsm1.NewValue(t, f).(tsm1.StringValue) } tests := []struct { a, b, exp []tsm1.StringValue }{ { // empty a a: []tsm1.StringValue{}, b: []tsm1.StringValue{ stringValue(1, "10"), stringValue(2, "20"), }, exp: []tsm1.StringValue{ stringValue(1, "10"), stringValue(2, "20"), }, }, { // empty b a: []tsm1.StringValue{ stringValue(1, "1"), stringValue(2, "2"), }, b: []tsm1.StringValue{}, exp: []tsm1.StringValue{ stringValue(1, "1"), stringValue(2, "2"), }, }, { a: []tsm1.StringValue{ stringValue(1, "1"), }, b: []tsm1.StringValue{ stringValue(0, "0"), stringValue(1, "10"), // overwrites a stringValue(2, "20"), stringValue(3, "30"), stringValue(4, "40"), }, exp: []tsm1.StringValue{ stringValue(0, "0"), stringValue(1, "10"), stringValue(2, "20"), stringValue(3, "30"), stringValue(4, "40"), }, }, { a: []tsm1.StringValue{ stringValue(1, "1"), stringValue(2, "2"), stringValue(3, "3"), stringValue(4, "4"), }, b: []tsm1.StringValue{ stringValue(1, "10"), // overwrites a stringValue(2, "20"), // overwrites a }, exp: []tsm1.StringValue{ stringValue(1, "10"), stringValue(2, "20"), stringValue(3, "3"), stringValue(4, "4"), }, }, { a: []tsm1.StringValue{ stringValue(1, "1"), stringValue(2, "2"), stringValue(3, "3"), stringValue(4, "4"), }, b: []tsm1.StringValue{ stringValue(1, "10"), // overwrites a stringValue(2, "20"), // overwrites a stringValue(3, "30"), stringValue(4, "40"), }, exp: []tsm1.StringValue{ stringValue(1, "10"), stringValue(2, "20"), stringValue(3, "30"), stringValue(4, "40"), }, }, { a: []tsm1.StringValue{ stringValue(0, "0"), stringValue(1, "1"), stringValue(2, "2"), stringValue(3, "3"), stringValue(4, "4"), }, b: []tsm1.StringValue{ stringValue(0, "0"), stringValue(2, "20"), stringValue(4, "40"), }, exp: []tsm1.StringValue{ stringValue(0, "0.0"), stringValue(1, "1"), stringValue(2, "20"), stringValue(3, "3"), stringValue(4, "40"), }, }, } for i, test := range tests { if i != 2 { continue } got := tsm1.StringValues(test.a).Merge(test.b) if exp, got := len(test.exp), len(got); exp != got { t.Fatalf("test(%d): value length mismatch: exp %v, got %v", i, exp, got) } dedup := tsm1.StringValues(append(test.a, test.b...)).Deduplicate() for i := range test.exp { if exp, got := test.exp[i].String(), got[i].String(); exp != got { t.Fatalf("value mismatch:\n exp %v\n got %v", exp, got) } if exp, got := test.exp[i].String(), dedup[i].String(); exp != got { t.Fatalf("value mismatch:\n exp %v\n got %v", exp, got) } } } } func getTimes(n, step int, precision time.Duration) []int64 { t := time.Now().Round(precision).UnixNano() a := make([]int64, n) for i := 0; i < n; i++ { a[i] = t + (time.Duration(i*60) * precision).Nanoseconds() } return a } func BenchmarkDecodeBlock_Float_Empty(b *testing.B) { valueCount := 1000 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) } var decodedValues []tsm1.Value b.ResetTimer() for i := 0; i < b.N; i++ { _, err = tsm1.DecodeBlock(bytes, decodedValues) if err != nil { b.Fatalf("unexpected error decoding block: %v", err) } } } func BenchmarkDecodeBlock_Float_EqualSize(b *testing.B) { valueCount := 1000 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) } decodedValues := make([]tsm1.Value, len(values)) b.ResetTimer() for i := 0; i < b.N; i++ { _, err = tsm1.DecodeBlock(bytes, decodedValues) if err != nil { b.Fatalf("unexpected error decoding block: %v", err) } } } func BenchmarkDecodeBlock_Float_TypeSpecific(b *testing.B) { valueCount := 1000 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) } decodedValues := make([]tsm1.FloatValue, len(values)) b.ResetTimer() for i := 0; i < b.N; i++ { _, err = tsm1.DecodeFloatBlock(bytes, &decodedValues) if err != nil { b.Fatalf("unexpected error decoding block: %v", err) } } } func BenchmarkDecodeBlock_Integer_Empty(b *testing.B) { valueCount := 1000 times := getTimes(valueCount, 60, time.Second) values := make([]tsm1.Value, len(times)) for i, t := range times { values[i] = tsm1.NewValue(t, int64(i)) } bytes, err := tsm1.Values(values).Encode(nil) if err != nil { b.Fatalf("unexpected error: %v", err) } var decodedValues []tsm1.Value b.ResetTimer() for i := 0; i < b.N; i++ { _, err = tsm1.DecodeBlock(bytes, decodedValues) if err != nil { b.Fatalf("unexpected error decoding block: %v", err) } } } func BenchmarkDecodeBlock_Integer_EqualSize(b *testing.B) { valueCount := 1000 times := getTimes(valueCount, 60, time.Second) values := make([]tsm1.Value, len(times)) for i, t := range times { values[i] = tsm1.NewValue(t, int64(i)) } bytes, err := tsm1.Values(values).Encode(nil) if err != nil { b.Fatalf("unexpected error: %v", err) } decodedValues := make([]tsm1.Value, len(values)) b.ResetTimer() for i := 0; i < b.N; i++ { _, err = tsm1.DecodeBlock(bytes, decodedValues) if err != nil { b.Fatalf("unexpected error decoding block: %v", err) } } } func BenchmarkDecodeBlock_Integer_TypeSpecific(b *testing.B) { valueCount := 1000 times := getTimes(valueCount, 60, time.Second) values := make([]tsm1.Value, len(times)) for i, t := range times { values[i] = tsm1.NewValue(t, int64(i)) } bytes, err := tsm1.Values(values).Encode(nil) if err != nil { b.Fatalf("unexpected error: %v", err) } decodedValues := make([]tsm1.IntegerValue, len(values)) b.ResetTimer() for i := 0; i < b.N; i++ { _, err = tsm1.DecodeIntegerBlock(bytes, &decodedValues) if err != nil { b.Fatalf("unexpected error decoding block: %v", err) } } } func BenchmarkDecodeBlock_Boolean_Empty(b *testing.B) { valueCount := 1000 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) } var decodedValues []tsm1.Value b.ResetTimer() for i := 0; i < b.N; i++ { _, err = tsm1.DecodeBlock(bytes, decodedValues) if err != nil { b.Fatalf("unexpected error decoding block: %v", err) } } } func BenchmarkDecodeBlock_Boolean_EqualSize(b *testing.B) { valueCount := 1000 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) } decodedValues := make([]tsm1.Value, len(values)) b.ResetTimer() for i := 0; i < b.N; i++ { _, err = tsm1.DecodeBlock(bytes, decodedValues) if err != nil { b.Fatalf("unexpected error decoding block: %v", err) } } } func BenchmarkDecodeBlock_Boolean_TypeSpecific(b *testing.B) { valueCount := 1000 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) } decodedValues := make([]tsm1.BooleanValue, len(values)) b.ResetTimer() for i := 0; i < b.N; i++ { _, err = tsm1.DecodeBooleanBlock(bytes, &decodedValues) if err != nil { b.Fatalf("unexpected error decoding block: %v", err) } } } 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) 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) } var decodedValues []tsm1.Value b.ResetTimer() for i := 0; i < b.N; i++ { _, err = tsm1.DecodeBlock(bytes, decodedValues) if err != nil { b.Fatalf("unexpected error decoding block: %v", err) } } } func BenchmarkDecodeBlock_String_EqualSize(b *testing.B) { valueCount := 1000 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) } decodedValues := make([]tsm1.Value, len(values)) b.ResetTimer() for i := 0; i < b.N; i++ { _, err = tsm1.DecodeBlock(bytes, decodedValues) if err != nil { b.Fatalf("unexpected error decoding block: %v", err) } } } func BenchmarkDecodeBlock_String_TypeSpecific(b *testing.B) { valueCount := 1000 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) } decodedValues := make([]tsm1.StringValue, len(values)) b.ResetTimer() for i := 0; i < b.N; i++ { _, err = tsm1.DecodeStringBlock(bytes, &decodedValues) if err != nil { b.Fatalf("unexpected error decoding block: %v", err) } } } func BenchmarkValues_Deduplicate(b *testing.B) { valueCount := 1000 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)) } values = append(values, values...) b.ResetTimer() for i := 0; i < b.N; i++ { tsm1.Values(values).Deduplicate() } } func BenchmarkValues_Merge(b *testing.B) { valueCount := 1000 times := getTimes(valueCount, 60, time.Second) a := make([]tsm1.Value, len(times)) c := make([]tsm1.Value, len(times)) for i, t := range times { a[i] = tsm1.NewValue(t, float64(i)) c[i] = tsm1.NewValue(t+1, float64(i)) } b.ResetTimer() benchmarkMerge(a, c, b) } func BenchmarkValues_MergeDisjoint(b *testing.B) { valueCount := 1000 times := getTimes(valueCount, 60, time.Second) a := make([]tsm1.Value, len(times)) c := make([]tsm1.Value, len(times)) for i, t := range times { a[i] = tsm1.NewValue(t, float64(i)) c[i] = tsm1.NewValue(times[len(times)-1]+int64((i+1)*1e9), float64(i)) } b.ResetTimer() benchmarkMerge(a, c, b) } func BenchmarkValues_MergeSame(b *testing.B) { valueCount := 1000 times := getTimes(valueCount, 60, time.Second) a := make([]tsm1.Value, len(times)) c := make([]tsm1.Value, len(times)) for i, t := range times { a[i] = tsm1.NewValue(t, float64(i)) c[i] = tsm1.NewValue(t, float64(i)) } b.ResetTimer() benchmarkMerge(a, c, b) } func BenchmarkValues_MergeSimilar(b *testing.B) { valueCount := 1000 times := getTimes(valueCount, 60, time.Second) a := make([]tsm1.Value, len(times)) c := make([]tsm1.Value, len(times)) for i, t := range times { a[i] = tsm1.NewValue(t, float64(i)) if i == 0 { t++ } c[i] = tsm1.NewValue(t, float64(i)) } b.ResetTimer() benchmarkMerge(a, c, b) } func BenchmarkValues_MergeUnevenA(b *testing.B) { valueCount := 1000 times := getTimes(valueCount, 60, time.Second) a := make([]tsm1.Value, len(times)) c := make([]tsm1.Value, len(times)) for i, t := range times { a[i] = tsm1.NewValue(t, float64(i)) c[i] = tsm1.NewValue(t, float64(i)) } b.ResetTimer() benchmarkMerge(a[:700], c[:10], b) } func BenchmarkValues_MergeUnevenB(b *testing.B) { valueCount := 1000 times := getTimes(valueCount, 60, time.Second) a := make([]tsm1.Value, len(times)) c := make([]tsm1.Value, len(times)) for i, t := range times { a[i] = tsm1.NewValue(t, float64(i)) c[i] = tsm1.NewValue(t, float64(i)) } b.ResetTimer() benchmarkMerge(a[:10], c[:700], b) } func benchmarkMerge(a, c tsm1.Values, b *testing.B) { for i := 0; i < b.N; i++ { b.StopTimer() aa := make(tsm1.Values, len(a)) copy(aa, a) cc := make(tsm1.Values, len(c)) copy(cc, c) b.StartTimer() tsm1.Values(aa).Merge(tsm1.Values(cc)) } } func BenchmarkValues_EncodeInteger(b *testing.B) { valueCount := 1024 times := getTimes(valueCount, 60, time.Second) a := make([]tsm1.Value, len(times)) for i, t := range times { a[i] = tsm1.NewValue(t, int64(i)) } buf := make([]byte, 1024*8) b.ResetTimer() for i := 0; i < b.N; i++ { tsm1.Values(a).Encode(buf) } } func BenchmarkValues_EncodeFloat(b *testing.B) { valueCount := 1024 times := getTimes(valueCount, 60, time.Second) a := make([]tsm1.Value, len(times)) for i, t := range times { a[i] = tsm1.NewValue(t, float64(i)) } buf := make([]byte, 1024*8) b.ResetTimer() for i := 0; i < b.N; i++ { tsm1.Values(a).Encode(buf) } } func BenchmarkValues_EncodeString(b *testing.B) { valueCount := 1024 times := getTimes(valueCount, 60, time.Second) a := make([]tsm1.Value, len(times)) for i, t := range times { a[i] = tsm1.NewValue(t, fmt.Sprintf("%d", i)) } buf := make([]byte, 1024*8) b.ResetTimer() for i := 0; i < b.N; i++ { tsm1.Values(a).Encode(buf) } } func BenchmarkValues_EncodeBool(b *testing.B) { valueCount := 1024 times := getTimes(valueCount, 60, time.Second) a := make([]tsm1.Value, len(times)) for i, t := range times { if i%2 == 0 { a[i] = tsm1.NewValue(t, true) } else { a[i] = tsm1.NewValue(t, false) } } buf := make([]byte, 1024*8) b.ResetTimer() for i := 0; i < b.N; i++ { tsm1.Values(a).Encode(buf) } }