Skip to content

Commit

Permalink
Remove generateFromTimeSeries and cleanup after that
Browse files Browse the repository at this point in the history
This does have some performance improvements due to having to not
support some cases.

name                                old time/op    new time/op    delta
CompileTemplatesSimple-8              1.05µs ±10%    0.98µs ±10%   -5.92%  (p=0.015 n=10+10)
CompileTemplatesComplex-8             1.54µs ± 7%    1.41µs ± 6%   -8.35%  (p=0.001 n=9+10)
EvaluateTemplatesSimple-8              230ns ± 7%      25ns ± 8%  -89.30%  (p=0.000 n=10+10)
EvaluateTemplatesComplex-8            6.88ns ± 6%    6.98ns ±10%     ~     (p=0.796 n=10+10)
StoreFromPrecompiledTemplates-8        155ms ±13%     153ms ± 7%     ~     (p=1.000 n=10+10)
StoreFromTemplates-8                   153ms ± 7%     158ms ±10%     ~     (p=0.243 n=10+9)
GenerateFromPrecompiledTemplates-8    31.6ms ±19%    27.4ms ±20%  -13.42%  (p=0.005 n=10+10)
WriteFor-8                            1.08µs ±10%    1.05µs ±11%     ~     (p=0.280 n=10+10)

name                                old alloc/op   new alloc/op   delta
StoreFromPrecompiledTemplates-8        117MB ± 0%     117MB ± 0%     ~     (p=1.000 n=10+9)
StoreFromTemplates-8                   117MB ± 0%     117MB ± 0%     ~     (p=0.143 n=10+10)
GenerateFromPrecompiledTemplates-8    79.2MB ± 0%    79.2MB ± 0%   -0.00%  (p=0.000 n=10+9)
WriteFor-8                              640B ± 5%      739B ±43%     ~     (p=0.795 n=7+10)

name                                old allocs/op  new allocs/op  delta
StoreFromPrecompiledTemplates-8          175 ± 2%       175 ± 1%     ~     (p=0.643 n=10+10)
StoreFromTemplates-8                     309 ± 1%       281 ± 1%   -9.22%  (p=0.000 n=10+10)
GenerateFromPrecompiledTemplates-8      39.0 ±21%      28.3 ±13%  -27.44%  (p=0.000 n=10+10)
WriteFor-8                              0.00           0.00          ~     (all equal)
  • Loading branch information
mstoykov committed Apr 1, 2022
1 parent 3895ea9 commit 56b0706
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 94 deletions.
40 changes: 4 additions & 36 deletions bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ import (
"testing"
"time"

"github.com/golang/protobuf/proto"
"github.com/oxtoacart/bpool"
"github.com/prometheus/prometheus/prompb"
"github.com/stretchr/testify/require"
"go.k6.io/k6/js/modulestest"
"go.k6.io/k6/lib"
Expand All @@ -38,17 +36,19 @@ func BenchmarkEvaluateTemplatesSimple(b *testing.B) {
t, err := compileTemplate("something ${series_id} else")
require.NoError(b, err)
b.ResetTimer()
var buf []byte
for i := 0; i < b.N; i++ {
_ = t.ToString(i)
buf = t.AppendByte(buf[:0], i)
}
}

func BenchmarkEvaluateTemplatesComplex(b *testing.B) {
t, err := compileTemplate("something ${series_id/1000} else")
require.NoError(b, err)
b.ResetTimer()
var buf []byte
for i := 0; i < b.N; i++ {
_ = t.ToString(i)
buf = t.AppendByte(buf[:0], i)
}
}

Expand Down Expand Up @@ -158,35 +158,3 @@ func BenchmarkGenerateFromPrecompiledTemplates(b *testing.B) {
}
})
}

func BenchmarkGenerateFromTemplates(b *testing.B) {
b.ReportAllocs()
b.RunParallel(func(pb *testing.PB) {
r := rand.New(rand.NewSource(time.Now().Unix()))
i := 0
for pb.Next() {
i++
_, err := generateFromTemplates(r, i, i+10, int64(i), 0, 100000, benchmarkLabels)
require.NoError(b, err)
}
})
}

func BenchmarkGenerateFromTemplatesAndMarshal(b *testing.B) {
b.ReportAllocs()
b.RunParallel(func(pb *testing.PB) {
r := rand.New(rand.NewSource(time.Now().Unix()))
i := 0
for pb.Next() {
i++
batch, err := generateFromTemplates(r, i, i+10, int64(i), 0, 100000, benchmarkLabels)
require.NoError(b, err)

req := prompb.WriteRequest{
Timeseries: batch,
}
_, err = proto.Marshal(&req)
require.NoError(b, err)
}
})
}
56 changes: 0 additions & 56 deletions remote_write.go
Original file line number Diff line number Diff line change
Expand Up @@ -329,9 +329,6 @@ func compileTemplate(template string) (*labelGenerator, error) {
switch template[i+len("${series_id")] {
case '}':
return &labelGenerator{
ToString: func(seriesID int) string {
return template[:i] + strconv.Itoa(seriesID) + template[i+len("${series_id}"):]
},
AppendByte: func(b []byte, seriesID int) []byte {
b = append(b, template[:i]...)
b = strconv.AppendInt(b, int64(seriesID), 10)
Expand All @@ -356,15 +353,7 @@ func compileTemplate(template string) (*labelGenerator, error) {
b = strconv.AppendInt(b, int64(j), 10)
possibleValues[j] = append(b, template[i+end+1:]...)
}
possibleValuesS := make([]string, d)
// TODO have an upper limit
for j := 0; j < d; j++ {
possibleValuesS[j] = template[:i] + strconv.Itoa((j)) + template[i+end+1:]
}
return &labelGenerator{
ToString: func(seriesID int) string {
return possibleValuesS[seriesID%d]
},
AppendByte: func(b []byte, seriesID int) []byte {
return append(b, possibleValues[seriesID%d]...)
},
Expand All @@ -378,20 +367,9 @@ func compileTemplate(template string) (*labelGenerator, error) {
if err != nil {
return nil, err
}
var memoizeS string
var memoizeSValue int

var memoize []byte
var memoizeValue int64
return &labelGenerator{
ToString: func(seriesID int) string {
value := (seriesID / d)
if memoizeS == "" || value != memoizeSValue {
memoizeSValue = value
memoizeS = template[:i] + strconv.Itoa(value) + template[i+end+1:]
}
return memoizeS
},
AppendByte: func(b []byte, seriesID int) []byte {
value := int64(seriesID / d)
if memoize == nil || value != memoizeValue {
Expand All @@ -409,49 +387,15 @@ func compileTemplate(template string) (*labelGenerator, error) {
}

type labelGenerator struct {
ToString func(int) string
AppendByte func([]byte, int) []byte
}

func newIdentityLabelGenerator(t string) *labelGenerator {
return &labelGenerator{
ToString: func(int) string { return t },
AppendByte: func(b []byte, _ int) []byte { return append(b, t...) },
}
}

func generateFromTemplates(r *rand.Rand, minValue, maxValue int,
timestamp int64, minSeriesID, maxSeriesID int,
labelsTemplate map[string]string,
) ([]prompb.TimeSeries, error) {
batchSize := maxSeriesID - minSeriesID
series := make([]prompb.TimeSeries, batchSize)

compiledTemplates, err := compileLabelTemplates(labelsTemplate)
if err != nil {
return nil, err
}
for seriesID := minSeriesID; seriesID < maxSeriesID; seriesID++ {
labels := make([]prompb.Label, len(labelsTemplate))
// TODO optimize
for i, template := range compiledTemplates.compiledTemplates {
labels[i] = prompb.Label{Name: template.name, Value: template.generator.ToString(seriesID)}
}

series[seriesID-minSeriesID] = prompb.TimeSeries{
Labels: labels,
Samples: []prompb.Sample{
{
Value: valueBetween(r, minValue, maxValue),
Timestamp: timestamp,
},
},
}
}

return series, nil
}

// this is opaque on purpose so that it can't be done anything to from the js side
type labelTemplates struct {
compiledTemplates []compiledTemplate
Expand Down
9 changes: 7 additions & 2 deletions remote_write_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func TestEvaluateTemplate(t *testing.T) {
return
}
require.NoError(t, err)
result := compiled.ToString(testcase.value)
result := string(compiled.AppendByte(nil, testcase.value))
require.Equal(t, testcase.result, result)
})
}
Expand Down Expand Up @@ -143,7 +143,12 @@ func TestGenerateFromTemplates(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := rand.New(rand.NewSource(time.Now().Unix()))
got, err := generateFromTemplates(r, tt.args.minValue, tt.args.maxValue, tt.args.timestamp, tt.args.minSeriesID, tt.args.maxSeriesID, tt.args.labelsTemplate)
compiled, err := compileLabelTemplates(tt.args.labelsTemplate)
require.NoError(t, err)
buf := generateFromPrecompiledTemplates(r, tt.args.minValue, tt.args.maxValue, tt.args.timestamp, tt.args.minSeriesID, tt.args.maxSeriesID, compiled)
req := new(prompb.WriteRequest)
require.NoError(t, proto.Unmarshal(buf.Bytes(), req))
got := req.Timeseries
require.NoError(t, err)
if len(got) != len(tt.want.series) {
t.Errorf("Differing length, want: %d, got: %d", len(tt.want.series), len(got))
Expand Down

0 comments on commit 56b0706

Please sign in to comment.