Enable reusing memory when converting between histogram types

The 'ToFloat' method on integer histograms currently allocates new memory
each time it is called.

This commit adds an optional *FloatHistogram parameter that can be used
to reuse span and bucket slices. It is up to the caller to make sure the
input float histogram is not used anymore after the call.

Signed-off-by: Filip Petkovski <filip.petkovsky@gmail.com>
This commit is contained in:
Filip Petkovski 2023-11-29 15:15:57 +01:00
parent 48b1818ee8
commit 10a82f87fd
No known key found for this signature in database
GPG key ID: 431B0F2E85E42402
20 changed files with 151 additions and 104 deletions

View file

@ -282,50 +282,49 @@ func (h *Histogram) Compact(maxEmptyBuckets int) *Histogram {
return h return h
} }
// ToFloat returns a FloatHistogram representation of the Histogram. It is a // ToFloat returns a FloatHistogram representation of the Histogram. It is a deep
// deep copy (e.g. spans are not shared). // copy (e.g. spans are not shared). The function accepts a FloatHistogram as an
func (h *Histogram) ToFloat() *FloatHistogram { // argument whose memory will be reused and overwritten if provided. If this
var ( // argument is nil, a new FloatHistogram will be allocated.
positiveSpans, negativeSpans []Span func (h *Histogram) ToFloat(fh *FloatHistogram) *FloatHistogram {
positiveBuckets, negativeBuckets []float64 if fh == nil {
) fh = &FloatHistogram{}
if len(h.PositiveSpans) != 0 {
positiveSpans = make([]Span, len(h.PositiveSpans))
copy(positiveSpans, h.PositiveSpans)
} }
if len(h.NegativeSpans) != 0 { fh.CounterResetHint = h.CounterResetHint
negativeSpans = make([]Span, len(h.NegativeSpans)) fh.Schema = h.Schema
copy(negativeSpans, h.NegativeSpans) fh.ZeroThreshold = h.ZeroThreshold
} fh.ZeroCount = float64(h.ZeroCount)
if len(h.PositiveBuckets) != 0 { fh.Count = float64(h.Count)
positiveBuckets = make([]float64, len(h.PositiveBuckets)) fh.Sum = h.Sum
var current float64
for i, b := range h.PositiveBuckets { fh.PositiveSpans = resize(fh.PositiveSpans, len(h.PositiveSpans))
current += float64(b) copy(fh.PositiveSpans, h.PositiveSpans)
positiveBuckets[i] = current
} fh.NegativeSpans = resize(fh.NegativeSpans, len(h.NegativeSpans))
} copy(fh.NegativeSpans, h.NegativeSpans)
if len(h.NegativeBuckets) != 0 {
negativeBuckets = make([]float64, len(h.NegativeBuckets)) fh.PositiveBuckets = resize(fh.PositiveBuckets, len(h.PositiveBuckets))
var current float64 var currentPositive float64
for i, b := range h.NegativeBuckets { for i, b := range h.PositiveBuckets {
current += float64(b) currentPositive += float64(b)
negativeBuckets[i] = current fh.PositiveBuckets[i] = currentPositive
}
} }
return &FloatHistogram{ fh.NegativeBuckets = resize(fh.NegativeBuckets, len(h.NegativeBuckets))
CounterResetHint: h.CounterResetHint, var currentNegative float64
Schema: h.Schema, for i, b := range h.NegativeBuckets {
ZeroThreshold: h.ZeroThreshold, currentNegative += float64(b)
ZeroCount: float64(h.ZeroCount), fh.NegativeBuckets[i] = currentNegative
Count: float64(h.Count),
Sum: h.Sum,
PositiveSpans: positiveSpans,
NegativeSpans: negativeSpans,
PositiveBuckets: positiveBuckets,
NegativeBuckets: negativeBuckets,
} }
return fh
}
func resize[T any](items []T, n int) []T {
if len(items) < n {
return make([]T, n)
}
return items[:n]
} }
// Validate validates consistency between span and bucket slices. Also, buckets are checked // Validate validates consistency between span and bucket slices. Also, buckets are checked

View file

@ -408,9 +408,57 @@ func TestHistogramToFloat(t *testing.T) {
}, },
NegativeBuckets: []int64{1, 2, -2, 1, -1, 0}, NegativeBuckets: []int64{1, 2, -2, 1, -1, 0},
} }
fh := h.ToFloat() cases := []struct {
name string
fh *FloatHistogram
}{
{name: "without prior float histogram"},
{name: "prior float histogram with more buckets", fh: &FloatHistogram{
Schema: 2,
Count: 3,
Sum: 5,
ZeroThreshold: 4,
ZeroCount: 1,
PositiveSpans: []Span{
{Offset: 1, Length: 2},
{Offset: 1, Length: 2},
{Offset: 1, Length: 2},
},
PositiveBuckets: []float64{1, 2, 3, 4, 5, 6, 7, 8, 9},
NegativeSpans: []Span{
{Offset: 20, Length: 6},
{Offset: 12, Length: 7},
{Offset: 33, Length: 10},
},
NegativeBuckets: []float64{1, 2, 3, 4, 5, 6, 7, 8, 9},
}},
{name: "prior float histogram with fewer buckets", fh: &FloatHistogram{
Schema: 2,
Count: 3,
Sum: 5,
ZeroThreshold: 4,
ZeroCount: 1,
PositiveSpans: []Span{
{Offset: 1, Length: 2},
{Offset: 1, Length: 2},
{Offset: 1, Length: 2},
},
PositiveBuckets: []float64{1, 2},
NegativeSpans: []Span{
{Offset: 20, Length: 6},
{Offset: 12, Length: 7},
{Offset: 33, Length: 10},
},
NegativeBuckets: []float64{1, 2},
}},
}
require.Equal(t, h.String(), fh.String()) for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
fh := h.ToFloat(c.fh)
require.Equal(t, h.String(), fh.String())
})
}
} }
// TestHistogramEquals tests both Histogram and FloatHistogram. // TestHistogramEquals tests both Histogram and FloatHistogram.
@ -436,14 +484,14 @@ func TestHistogramEquals(t *testing.T) {
equals := func(h1, h2 Histogram) { equals := func(h1, h2 Histogram) {
require.True(t, h1.Equals(&h2)) require.True(t, h1.Equals(&h2))
require.True(t, h2.Equals(&h1)) require.True(t, h2.Equals(&h1))
h1f, h2f := h1.ToFloat(), h2.ToFloat() h1f, h2f := h1.ToFloat(nil), h2.ToFloat(nil)
require.True(t, h1f.Equals(h2f)) require.True(t, h1f.Equals(h2f))
require.True(t, h2f.Equals(h1f)) require.True(t, h2f.Equals(h1f))
} }
notEquals := func(h1, h2 Histogram) { notEquals := func(h1, h2 Histogram) {
require.False(t, h1.Equals(&h2)) require.False(t, h1.Equals(&h2))
require.False(t, h2.Equals(&h1)) require.False(t, h2.Equals(&h1))
h1f, h2f := h1.ToFloat(), h2.ToFloat() h1f, h2f := h1.ToFloat(nil), h2.ToFloat(nil)
require.False(t, h1f.Equals(h2f)) require.False(t, h1f.Equals(h2f))
require.False(t, h2f.Equals(h1f)) require.False(t, h2f.Equals(h1f))
} }
@ -950,7 +998,7 @@ func TestHistogramValidation(t *testing.T) {
return return
} }
fh := tc.h.ToFloat() fh := tc.h.ToFloat(nil)
if err := fh.Validate(); tc.errMsg != "" { if err := fh.Validate(); tc.errMsg != "" {
require.EqualError(t, err, tc.errMsg) require.EqualError(t, err, tc.errMsg)
} else { } else {

View file

@ -3267,7 +3267,7 @@ func TestNativeHistogram_HistogramCountAndSum(t *testing.T) {
app := storage.Appender(context.Background()) app := storage.Appender(context.Background())
var err error var err error
if floatHisto { if floatHisto {
_, err = app.AppendHistogram(0, lbls, ts, nil, h.ToFloat()) _, err = app.AppendHistogram(0, lbls, ts, nil, h.ToFloat(nil))
} else { } else {
_, err = app.AppendHistogram(0, lbls, ts, h, nil) _, err = app.AppendHistogram(0, lbls, ts, h, nil)
} }
@ -3287,7 +3287,7 @@ func TestNativeHistogram_HistogramCountAndSum(t *testing.T) {
require.Len(t, vector, 1) require.Len(t, vector, 1)
require.Nil(t, vector[0].H) require.Nil(t, vector[0].H)
if floatHisto { if floatHisto {
require.Equal(t, h.ToFloat().Count, vector[0].F) require.Equal(t, h.ToFloat(nil).Count, vector[0].F)
} else { } else {
require.Equal(t, float64(h.Count), vector[0].F) require.Equal(t, float64(h.Count), vector[0].F)
} }
@ -3305,7 +3305,7 @@ func TestNativeHistogram_HistogramCountAndSum(t *testing.T) {
require.Len(t, vector, 1) require.Len(t, vector, 1)
require.Nil(t, vector[0].H) require.Nil(t, vector[0].H)
if floatHisto { if floatHisto {
require.Equal(t, h.ToFloat().Sum, vector[0].F) require.Equal(t, h.ToFloat(nil).Sum, vector[0].F)
} else { } else {
require.Equal(t, h.Sum, vector[0].F) require.Equal(t, h.Sum, vector[0].F)
} }
@ -3433,7 +3433,7 @@ func TestNativeHistogram_HistogramStdDevVar(t *testing.T) {
app := storage.Appender(context.Background()) app := storage.Appender(context.Background())
var err error var err error
if floatHisto { if floatHisto {
_, err = app.AppendHistogram(0, lbls, ts, nil, tc.h.ToFloat()) _, err = app.AppendHistogram(0, lbls, ts, nil, tc.h.ToFloat(nil))
} else { } else {
_, err = app.AppendHistogram(0, lbls, ts, tc.h, nil) _, err = app.AppendHistogram(0, lbls, ts, tc.h, nil)
} }
@ -3678,7 +3678,7 @@ func TestNativeHistogram_HistogramQuantile(t *testing.T) {
app := storage.Appender(context.Background()) app := storage.Appender(context.Background())
var err error var err error
if floatHisto { if floatHisto {
_, err = app.AppendHistogram(0, lbls, ts, nil, c.h.ToFloat()) _, err = app.AppendHistogram(0, lbls, ts, nil, c.h.ToFloat(nil))
} else { } else {
_, err = app.AppendHistogram(0, lbls, ts, c.h, nil) _, err = app.AppendHistogram(0, lbls, ts, c.h, nil)
} }
@ -4109,7 +4109,7 @@ func TestNativeHistogram_HistogramFraction(t *testing.T) {
app := storage.Appender(context.Background()) app := storage.Appender(context.Background())
var err error var err error
if floatHisto { if floatHisto {
_, err = app.AppendHistogram(0, lbls, ts, nil, c.h.ToFloat()) _, err = app.AppendHistogram(0, lbls, ts, nil, c.h.ToFloat(nil))
} else { } else {
_, err = app.AppendHistogram(0, lbls, ts, c.h, nil) _, err = app.AppendHistogram(0, lbls, ts, c.h, nil)
} }
@ -4272,7 +4272,7 @@ func TestNativeHistogram_Sum_Count_Add_AvgOperator(t *testing.T) {
// Since we mutate h later, we need to create a copy here. // Since we mutate h later, we need to create a copy here.
var err error var err error
if floatHisto { if floatHisto {
_, err = app.AppendHistogram(0, lbls, ts, nil, h.Copy().ToFloat()) _, err = app.AppendHistogram(0, lbls, ts, nil, h.Copy().ToFloat(nil))
} else { } else {
_, err = app.AppendHistogram(0, lbls, ts, h.Copy(), nil) _, err = app.AppendHistogram(0, lbls, ts, h.Copy(), nil)
} }
@ -4282,7 +4282,7 @@ func TestNativeHistogram_Sum_Count_Add_AvgOperator(t *testing.T) {
newTs := ts + int64(idx1)*int64(time.Minute/time.Millisecond) newTs := ts + int64(idx1)*int64(time.Minute/time.Millisecond)
// Since we mutate h later, we need to create a copy here. // Since we mutate h later, we need to create a copy here.
if floatHisto { if floatHisto {
_, err = app.AppendHistogram(0, lbls, newTs, nil, h.Copy().ToFloat()) _, err = app.AppendHistogram(0, lbls, newTs, nil, h.Copy().ToFloat(nil))
} else { } else {
_, err = app.AppendHistogram(0, lbls, newTs, h.Copy(), nil) _, err = app.AppendHistogram(0, lbls, newTs, h.Copy(), nil)
} }
@ -4530,7 +4530,7 @@ func TestNativeHistogram_SubOperator(t *testing.T) {
// Since we mutate h later, we need to create a copy here. // Since we mutate h later, we need to create a copy here.
var err error var err error
if floatHisto { if floatHisto {
_, err = app.AppendHistogram(0, lbls, ts, nil, h.Copy().ToFloat()) _, err = app.AppendHistogram(0, lbls, ts, nil, h.Copy().ToFloat(nil))
} else { } else {
_, err = app.AppendHistogram(0, lbls, ts, h.Copy(), nil) _, err = app.AppendHistogram(0, lbls, ts, h.Copy(), nil)
} }
@ -4687,7 +4687,7 @@ func TestNativeHistogram_MulDivOperator(t *testing.T) {
// Since we mutate h later, we need to create a copy here. // Since we mutate h later, we need to create a copy here.
var err error var err error
if floatHisto { if floatHisto {
_, err = app.AppendHistogram(0, lbls, ts, nil, h.Copy().ToFloat()) _, err = app.AppendHistogram(0, lbls, ts, nil, h.Copy().ToFloat(nil))
} else { } else {
_, err = app.AppendHistogram(0, lbls, ts, h.Copy(), nil) _, err = app.AppendHistogram(0, lbls, ts, h.Copy(), nil)
} }

View file

@ -1390,9 +1390,9 @@ func TestNativeHistogramsInRecordingRules(t *testing.T) {
require.Equal(t, labels.FromStrings("__name__", "sum:histogram_metric"), s.Labels()) require.Equal(t, labels.FromStrings("__name__", "sum:histogram_metric"), s.Labels())
expHist := hists[0].ToFloat() expHist := hists[0].ToFloat(nil)
for _, h := range hists[1:] { for _, h := range hists[1:] {
expHist = expHist.Add(h.ToFloat()) expHist = expHist.Add(h.ToFloat(nil))
} }
it := s.Iterator(nil) it := s.Iterator(nil)

View file

@ -565,7 +565,7 @@ func TestBucketLimitAppender(t *testing.T) {
lbls := labels.FromStrings("__name__", "sparse_histogram_series") lbls := labels.FromStrings("__name__", "sparse_histogram_series")
var err error var err error
if floatHisto { if floatHisto {
fh := c.h.Copy().ToFloat() fh := c.h.Copy().ToFloat(nil)
_, err = app.AppendHistogram(0, lbls, ts, nil, fh) _, err = app.AppendHistogram(0, lbls, ts, nil, fh)
if c.expectError { if c.expectError {
require.Error(t, err) require.Error(t, err)

View file

@ -202,7 +202,7 @@ func (s hSample) H() *histogram.Histogram {
} }
func (s hSample) FH() *histogram.FloatHistogram { func (s hSample) FH() *histogram.FloatHistogram {
return s.h.ToFloat() return s.h.ToFloat(nil)
} }
func (s hSample) Type() chunkenc.ValueType { func (s hSample) Type() chunkenc.ValueType {
@ -376,7 +376,7 @@ func (it *sampleRingIterator) AtHistogram() (int64, *histogram.Histogram) {
func (it *sampleRingIterator) AtFloatHistogram() (int64, *histogram.FloatHistogram) { func (it *sampleRingIterator) AtFloatHistogram() (int64, *histogram.FloatHistogram) {
if it.fh == nil { if it.fh == nil {
return it.t, it.h.ToFloat() return it.t, it.h.ToFloat(nil)
} }
return it.t, it.fh return it.t, it.fh
} }

View file

@ -233,7 +233,7 @@ func TestBufferedSeriesIteratorMixedHistograms(t *testing.T) {
histograms := tsdbutil.GenerateTestHistograms(2) histograms := tsdbutil.GenerateTestHistograms(2)
it := NewBufferIterator(NewListSeriesIterator(samples{ it := NewBufferIterator(NewListSeriesIterator(samples{
fhSample{t: 1, fh: histograms[0].ToFloat()}, fhSample{t: 1, fh: histograms[0].ToFloat(nil)},
hSample{t: 2, h: histograms[1]}, hSample{t: 2, h: histograms[1]},
}), 2) }), 2)
@ -244,11 +244,11 @@ func TestBufferedSeriesIteratorMixedHistograms(t *testing.T) {
require.Equal(t, chunkenc.ValFloatHistogram, buf.Next()) require.Equal(t, chunkenc.ValFloatHistogram, buf.Next())
_, fh := buf.AtFloatHistogram() _, fh := buf.AtFloatHistogram()
require.Equal(t, histograms[0].ToFloat(), fh) require.Equal(t, histograms[0].ToFloat(nil), fh)
require.Equal(t, chunkenc.ValHistogram, buf.Next()) require.Equal(t, chunkenc.ValHistogram, buf.Next())
_, fh = buf.AtFloatHistogram() _, fh = buf.AtFloatHistogram()
require.Equal(t, histograms[1].ToFloat(), fh) require.Equal(t, histograms[1].ToFloat(nil), fh)
} }
func BenchmarkBufferedSeriesIterator(b *testing.B) { func BenchmarkBufferedSeriesIterator(b *testing.B) {

View file

@ -57,7 +57,7 @@ var writeRequestFixture = &prompb.WriteRequest{
}, },
Samples: []prompb.Sample{{Value: 1, Timestamp: 0}}, Samples: []prompb.Sample{{Value: 1, Timestamp: 0}},
Exemplars: []prompb.Exemplar{{Labels: []prompb.Label{{Name: "f", Value: "g"}}, Value: 1, Timestamp: 0}}, Exemplars: []prompb.Exemplar{{Labels: []prompb.Label{{Name: "f", Value: "g"}}, Value: 1, Timestamp: 0}},
Histograms: []prompb.Histogram{HistogramToHistogramProto(0, &testHistogram), FloatHistogramToHistogramProto(1, testHistogram.ToFloat())}, Histograms: []prompb.Histogram{HistogramToHistogramProto(0, &testHistogram), FloatHistogramToHistogramProto(1, testHistogram.ToFloat(nil))},
}, },
{ {
Labels: []prompb.Label{ Labels: []prompb.Label{
@ -69,7 +69,7 @@ var writeRequestFixture = &prompb.WriteRequest{
}, },
Samples: []prompb.Sample{{Value: 2, Timestamp: 1}}, Samples: []prompb.Sample{{Value: 2, Timestamp: 1}},
Exemplars: []prompb.Exemplar{{Labels: []prompb.Label{{Name: "h", Value: "i"}}, Value: 2, Timestamp: 1}}, Exemplars: []prompb.Exemplar{{Labels: []prompb.Label{{Name: "h", Value: "i"}}, Value: 2, Timestamp: 1}},
Histograms: []prompb.Histogram{HistogramToHistogramProto(2, &testHistogram), FloatHistogramToHistogramProto(3, testHistogram.ToFloat())}, Histograms: []prompb.Histogram{HistogramToHistogramProto(2, &testHistogram), FloatHistogramToHistogramProto(3, testHistogram.ToFloat(nil))},
}, },
}, },
} }

View file

@ -619,7 +619,7 @@ func createHistograms(numSamples, numSeries int, floatHistogram bool) ([]record.
fh := record.RefFloatHistogramSample{ fh := record.RefFloatHistogramSample{
Ref: chunks.HeadSeriesRef(i), Ref: chunks.HeadSeriesRef(i),
T: int64(j), T: int64(j),
FH: hist.ToFloat(), FH: hist.ToFloat(nil),
} }
floatHistograms = append(floatHistograms, fh) floatHistograms = append(floatHistograms, fh)
} else { } else {

View file

@ -134,7 +134,7 @@ func TestOutOfOrderExemplar(t *testing.T) {
func TestOutOfOrderHistogram(t *testing.T) { func TestOutOfOrderHistogram(t *testing.T) {
buf, _, err := buildWriteRequest([]prompb.TimeSeries{{ buf, _, err := buildWriteRequest([]prompb.TimeSeries{{
Labels: []prompb.Label{{Name: "__name__", Value: "test_metric"}}, Labels: []prompb.Label{{Name: "__name__", Value: "test_metric"}},
Histograms: []prompb.Histogram{HistogramToHistogramProto(0, &testHistogram), FloatHistogramToHistogramProto(1, testHistogram.ToFloat())}, Histograms: []prompb.Histogram{HistogramToHistogramProto(0, &testHistogram), FloatHistogramToHistogramProto(1, testHistogram.ToFloat(nil))},
}}, nil, nil, nil) }}, nil, nil, nil)
require.NoError(t, err) require.NoError(t, err)

View file

@ -656,7 +656,7 @@ func genHistogramSeries(totalSeries, labelCount int, mint, maxt, step int64, flo
h.CounterResetHint = histogram.NotCounterReset h.CounterResetHint = histogram.NotCounterReset
} }
if floatHistogram { if floatHistogram {
return sample{t: ts, fh: h.ToFloat()} return sample{t: ts, fh: h.ToFloat(nil)}
} }
return sample{t: ts, h: h} return sample{t: ts, h: h}
}) })
@ -692,7 +692,7 @@ func genHistogramAndFloatSeries(totalSeries, labelCount int, mint, maxt, step in
h.CounterResetHint = histogram.NotCounterReset h.CounterResetHint = histogram.NotCounterReset
} }
if floatHistogram { if floatHistogram {
s = sample{t: ts, fh: h.ToFloat()} s = sample{t: ts, fh: h.ToFloat(nil)}
} else { } else {
s = sample{t: ts, h: h} s = sample{t: ts, h: h}
} }

View file

@ -94,10 +94,10 @@ func TestFloatHistogramChunkSameBuckets(t *testing.T) {
}, },
NegativeBuckets: []int64{2, 1, -1, -1}, // counts: 2, 3, 2, 1 (total 8) NegativeBuckets: []int64{2, 1, -1, -1}, // counts: 2, 3, 2, 1 (total 8)
} }
chk, _, app, err := app.AppendFloatHistogram(nil, ts, h.ToFloat(), false) chk, _, app, err := app.AppendFloatHistogram(nil, ts, h.ToFloat(nil), false)
require.NoError(t, err) require.NoError(t, err)
require.Nil(t, chk) require.Nil(t, chk)
exp = append(exp, floatResult{t: ts, h: h.ToFloat()}) exp = append(exp, floatResult{t: ts, h: h.ToFloat(nil)})
require.Equal(t, 1, c.NumSamples()) require.Equal(t, 1, c.NumSamples())
// Add an updated histogram. // Add an updated histogram.
@ -108,10 +108,10 @@ func TestFloatHistogramChunkSameBuckets(t *testing.T) {
h.Sum = 24.4 h.Sum = 24.4
h.PositiveBuckets = []int64{5, -2, 1, -2} // counts: 5, 3, 4, 2 (total 14) h.PositiveBuckets = []int64{5, -2, 1, -2} // counts: 5, 3, 4, 2 (total 14)
h.NegativeBuckets = []int64{4, -1, 1, -1} // counts: 4, 3, 4, 4 (total 15) h.NegativeBuckets = []int64{4, -1, 1, -1} // counts: 4, 3, 4, 4 (total 15)
chk, _, _, err = app.AppendFloatHistogram(nil, ts, h.ToFloat(), false) chk, _, _, err = app.AppendFloatHistogram(nil, ts, h.ToFloat(nil), false)
require.NoError(t, err) require.NoError(t, err)
require.Nil(t, chk) require.Nil(t, chk)
expH := h.ToFloat() expH := h.ToFloat(nil)
expH.CounterResetHint = histogram.NotCounterReset expH.CounterResetHint = histogram.NotCounterReset
exp = append(exp, floatResult{t: ts, h: expH}) exp = append(exp, floatResult{t: ts, h: expH})
require.Equal(t, 2, c.NumSamples()) require.Equal(t, 2, c.NumSamples())
@ -127,10 +127,10 @@ func TestFloatHistogramChunkSameBuckets(t *testing.T) {
h.Sum = 24.4 h.Sum = 24.4
h.PositiveBuckets = []int64{6, 1, -3, 6} // counts: 6, 7, 4, 10 (total 27) h.PositiveBuckets = []int64{6, 1, -3, 6} // counts: 6, 7, 4, 10 (total 27)
h.NegativeBuckets = []int64{5, 1, -2, 3} // counts: 5, 6, 4, 7 (total 22) h.NegativeBuckets = []int64{5, 1, -2, 3} // counts: 5, 6, 4, 7 (total 22)
chk, _, _, err = app.AppendFloatHistogram(nil, ts, h.ToFloat(), false) chk, _, _, err = app.AppendFloatHistogram(nil, ts, h.ToFloat(nil), false)
require.NoError(t, err) require.NoError(t, err)
require.Nil(t, chk) require.Nil(t, chk)
expH = h.ToFloat() expH = h.ToFloat(nil)
expH.CounterResetHint = histogram.NotCounterReset expH.CounterResetHint = histogram.NotCounterReset
exp = append(exp, floatResult{t: ts, h: expH}) exp = append(exp, floatResult{t: ts, h: expH})
require.Equal(t, 3, c.NumSamples()) require.Equal(t, 3, c.NumSamples())
@ -217,7 +217,7 @@ func TestFloatHistogramChunkBucketChanges(t *testing.T) {
NegativeBuckets: []int64{1}, NegativeBuckets: []int64{1},
} }
chk, _, app, err := app.AppendFloatHistogram(nil, ts1, h1.ToFloat(), false) chk, _, app, err := app.AppendFloatHistogram(nil, ts1, h1.ToFloat(nil), false)
require.NoError(t, err) require.NoError(t, err)
require.Nil(t, chk) require.Nil(t, chk)
require.Equal(t, 1, c.NumSamples()) require.Equal(t, 1, c.NumSamples())
@ -245,13 +245,13 @@ func TestFloatHistogramChunkBucketChanges(t *testing.T) {
h2.NegativeBuckets = []int64{2, -1} // 2 1 (total 3) h2.NegativeBuckets = []int64{2, -1} // 2 1 (total 3)
// This is how span changes will be handled. // This is how span changes will be handled.
hApp, _ := app.(*FloatHistogramAppender) hApp, _ := app.(*FloatHistogramAppender)
posInterjections, negInterjections, ok, cr := hApp.appendable(h2.ToFloat()) posInterjections, negInterjections, ok, cr := hApp.appendable(h2.ToFloat(nil))
require.NotEmpty(t, posInterjections) require.NotEmpty(t, posInterjections)
require.NotEmpty(t, negInterjections) require.NotEmpty(t, negInterjections)
require.True(t, ok) // Only new buckets came in. require.True(t, ok) // Only new buckets came in.
require.False(t, cr) require.False(t, cr)
c, app = hApp.recode(posInterjections, negInterjections, h2.PositiveSpans, h2.NegativeSpans) c, app = hApp.recode(posInterjections, negInterjections, h2.PositiveSpans, h2.NegativeSpans)
chk, _, _, err = app.AppendFloatHistogram(nil, ts2, h2.ToFloat(), false) chk, _, _, err = app.AppendFloatHistogram(nil, ts2, h2.ToFloat(nil), false)
require.NoError(t, err) require.NoError(t, err)
require.Nil(t, chk) require.Nil(t, chk)
require.Equal(t, 2, c.NumSamples()) require.Equal(t, 2, c.NumSamples())
@ -263,10 +263,10 @@ func TestFloatHistogramChunkBucketChanges(t *testing.T) {
h1.PositiveBuckets = []int64{6, -3, -3, 3, -3, 0, 2, 2, 1, -5, 1} h1.PositiveBuckets = []int64{6, -3, -3, 3, -3, 0, 2, 2, 1, -5, 1}
h1.NegativeSpans = h2.NegativeSpans h1.NegativeSpans = h2.NegativeSpans
h1.NegativeBuckets = []int64{0, 1} h1.NegativeBuckets = []int64{0, 1}
expH2 := h2.ToFloat() expH2 := h2.ToFloat(nil)
expH2.CounterResetHint = histogram.NotCounterReset expH2.CounterResetHint = histogram.NotCounterReset
exp := []floatResult{ exp := []floatResult{
{t: ts1, h: h1.ToFloat()}, {t: ts1, h: h1.ToFloat(nil)},
{t: ts2, h: expH2}, {t: ts2, h: expH2},
} }
it := c.Iterator(nil) it := c.Iterator(nil)

View file

@ -98,7 +98,7 @@ func TestHistogramChunkSameBuckets(t *testing.T) {
chk, _, app, err := app.AppendHistogram(nil, ts, h, false) chk, _, app, err := app.AppendHistogram(nil, ts, h, false)
require.NoError(t, err) require.NoError(t, err)
require.Nil(t, chk) require.Nil(t, chk)
exp = append(exp, result{t: ts, h: h, fh: h.ToFloat()}) exp = append(exp, result{t: ts, h: h, fh: h.ToFloat(nil)})
require.Equal(t, 1, c.NumSamples()) require.Equal(t, 1, c.NumSamples())
// Add an updated histogram. // Add an updated histogram.
@ -114,7 +114,7 @@ func TestHistogramChunkSameBuckets(t *testing.T) {
require.Nil(t, chk) require.Nil(t, chk)
hExp := h.Copy() hExp := h.Copy()
hExp.CounterResetHint = histogram.NotCounterReset hExp.CounterResetHint = histogram.NotCounterReset
exp = append(exp, result{t: ts, h: hExp, fh: hExp.ToFloat()}) exp = append(exp, result{t: ts, h: hExp, fh: hExp.ToFloat(nil)})
require.Equal(t, 2, c.NumSamples()) require.Equal(t, 2, c.NumSamples())
// Add update with new appender. // Add update with new appender.
@ -133,7 +133,7 @@ func TestHistogramChunkSameBuckets(t *testing.T) {
require.Nil(t, chk) require.Nil(t, chk)
hExp = h.Copy() hExp = h.Copy()
hExp.CounterResetHint = histogram.NotCounterReset hExp.CounterResetHint = histogram.NotCounterReset
exp = append(exp, result{t: ts, h: hExp, fh: hExp.ToFloat()}) exp = append(exp, result{t: ts, h: hExp, fh: hExp.ToFloat(nil)})
require.Equal(t, 3, c.NumSamples()) require.Equal(t, 3, c.NumSamples())
// 1. Expand iterator in simple case. // 1. Expand iterator in simple case.
@ -278,8 +278,8 @@ func TestHistogramChunkBucketChanges(t *testing.T) {
hExp := h2.Copy() hExp := h2.Copy()
hExp.CounterResetHint = histogram.NotCounterReset hExp.CounterResetHint = histogram.NotCounterReset
exp := []result{ exp := []result{
{t: ts1, h: h1, fh: h1.ToFloat()}, {t: ts1, h: h1, fh: h1.ToFloat(nil)},
{t: ts2, h: hExp, fh: hExp.ToFloat()}, {t: ts2, h: hExp, fh: hExp.ToFloat(nil)},
} }
it := c.Iterator(nil) it := c.Iterator(nil)
var act []result var act []result

View file

@ -1402,8 +1402,8 @@ func TestHeadCompactionWithHistograms(t *testing.T) {
for tsMinute := from; tsMinute <= to; tsMinute++ { for tsMinute := from; tsMinute <= to; tsMinute++ {
var err error var err error
if floatTest { if floatTest {
_, err = app.AppendHistogram(0, lbls, minute(tsMinute), nil, h.ToFloat()) _, err = app.AppendHistogram(0, lbls, minute(tsMinute), nil, h.ToFloat(nil))
efh := h.ToFloat() efh := h.ToFloat(nil)
if tsMinute == from { if tsMinute == from {
efh.CounterResetHint = histogram.UnknownCounterReset efh.CounterResetHint = histogram.UnknownCounterReset
} else { } else {

View file

@ -519,7 +519,7 @@ func TestAmendHistogramDatapointCausesError(t *testing.T) {
}, },
PositiveBuckets: []int64{1, 2, -2, 1, -1, 0, 0}, PositiveBuckets: []int64{1, 2, -2, 1, -1, 0, 0},
} }
fh := h.ToFloat() fh := h.ToFloat(nil)
app = db.Appender(ctx) app = db.Appender(ctx)
_, err = app.AppendHistogram(0, labels.FromStrings("a", "c"), 0, h.Copy(), nil) _, err = app.AppendHistogram(0, labels.FromStrings("a", "c"), 0, h.Copy(), nil)
@ -6392,8 +6392,8 @@ func testHistogramAppendAndQueryHelper(t *testing.T, floatHistogram bool) {
var err error var err error
app := db.Appender(ctx) app := db.Appender(ctx)
if floatHistogram { if floatHistogram {
_, err = app.AppendHistogram(0, lbls, minute(tsMinute), nil, h.ToFloat()) _, err = app.AppendHistogram(0, lbls, minute(tsMinute), nil, h.ToFloat(nil))
efh := h.ToFloat() efh := h.ToFloat(nil)
efh.CounterResetHint = expCRH efh.CounterResetHint = expCRH
*exp = append(*exp, sample{t: minute(tsMinute), fh: efh}) *exp = append(*exp, sample{t: minute(tsMinute), fh: efh})
} else { } else {
@ -6814,20 +6814,20 @@ func TestNativeHistogramFlag(t *testing.T) {
// Disabled by default. // Disabled by default.
_, err = app.AppendHistogram(0, l, 100, h, nil) _, err = app.AppendHistogram(0, l, 100, h, nil)
require.Equal(t, storage.ErrNativeHistogramsDisabled, err) require.Equal(t, storage.ErrNativeHistogramsDisabled, err)
_, err = app.AppendHistogram(0, l, 105, nil, h.ToFloat()) _, err = app.AppendHistogram(0, l, 105, nil, h.ToFloat(nil))
require.Equal(t, storage.ErrNativeHistogramsDisabled, err) require.Equal(t, storage.ErrNativeHistogramsDisabled, err)
// Enable and append. // Enable and append.
db.EnableNativeHistograms() db.EnableNativeHistograms()
_, err = app.AppendHistogram(0, l, 200, h, nil) _, err = app.AppendHistogram(0, l, 200, h, nil)
require.NoError(t, err) require.NoError(t, err)
_, err = app.AppendHistogram(0, l, 205, nil, h.ToFloat()) _, err = app.AppendHistogram(0, l, 205, nil, h.ToFloat(nil))
require.NoError(t, err) require.NoError(t, err)
db.DisableNativeHistograms() db.DisableNativeHistograms()
_, err = app.AppendHistogram(0, l, 300, h, nil) _, err = app.AppendHistogram(0, l, 300, h, nil)
require.Equal(t, storage.ErrNativeHistogramsDisabled, err) require.Equal(t, storage.ErrNativeHistogramsDisabled, err)
_, err = app.AppendHistogram(0, l, 305, nil, h.ToFloat()) _, err = app.AppendHistogram(0, l, 305, nil, h.ToFloat(nil))
require.Equal(t, storage.ErrNativeHistogramsDisabled, err) require.Equal(t, storage.ErrNativeHistogramsDisabled, err)
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
@ -6836,7 +6836,7 @@ func TestNativeHistogramFlag(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
act := query(t, q, labels.MustNewMatcher(labels.MatchEqual, "foo", "bar")) act := query(t, q, labels.MustNewMatcher(labels.MatchEqual, "foo", "bar"))
require.Equal(t, map[string][]chunks.Sample{ require.Equal(t, map[string][]chunks.Sample{
l.String(): {sample{t: 200, h: h}, sample{t: 205, fh: h.ToFloat()}}, l.String(): {sample{t: 200, h: h}, sample{t: 205, fh: h.ToFloat(nil)}},
}, act) }, act)
} }

View file

@ -4082,8 +4082,8 @@ func testHistogramStaleSampleHelper(t *testing.T, floatHistogram bool) {
for _, h := range tsdbutil.GenerateTestHistograms(numHistograms) { for _, h := range tsdbutil.GenerateTestHistograms(numHistograms) {
var err error var err error
if floatHistogram { if floatHistogram {
_, err = app.AppendHistogram(0, l, 100*int64(len(expHistograms)), nil, h.ToFloat()) _, err = app.AppendHistogram(0, l, 100*int64(len(expHistograms)), nil, h.ToFloat(nil))
expHistograms = append(expHistograms, timedHistogram{t: 100 * int64(len(expHistograms)), fh: h.ToFloat()}) expHistograms = append(expHistograms, timedHistogram{t: 100 * int64(len(expHistograms)), fh: h.ToFloat(nil)})
} else { } else {
_, err = app.AppendHistogram(0, l, 100*int64(len(expHistograms)), h, nil) _, err = app.AppendHistogram(0, l, 100*int64(len(expHistograms)), h, nil)
expHistograms = append(expHistograms, timedHistogram{t: 100 * int64(len(expHistograms)), h: h}) expHistograms = append(expHistograms, timedHistogram{t: 100 * int64(len(expHistograms)), h: h})
@ -4113,8 +4113,8 @@ func testHistogramStaleSampleHelper(t *testing.T, floatHistogram bool) {
for _, h := range tsdbutil.GenerateTestHistograms(2 * numHistograms)[numHistograms:] { for _, h := range tsdbutil.GenerateTestHistograms(2 * numHistograms)[numHistograms:] {
var err error var err error
if floatHistogram { if floatHistogram {
_, err = app.AppendHistogram(0, l, 100*int64(len(expHistograms)), nil, h.ToFloat()) _, err = app.AppendHistogram(0, l, 100*int64(len(expHistograms)), nil, h.ToFloat(nil))
expHistograms = append(expHistograms, timedHistogram{t: 100 * int64(len(expHistograms)), fh: h.ToFloat()}) expHistograms = append(expHistograms, timedHistogram{t: 100 * int64(len(expHistograms)), fh: h.ToFloat(nil)})
} else { } else {
_, err = app.AppendHistogram(0, l, 100*int64(len(expHistograms)), h, nil) _, err = app.AppendHistogram(0, l, 100*int64(len(expHistograms)), h, nil)
expHistograms = append(expHistograms, timedHistogram{t: 100 * int64(len(expHistograms)), h: h}) expHistograms = append(expHistograms, timedHistogram{t: 100 * int64(len(expHistograms)), h: h})
@ -4160,7 +4160,7 @@ func TestHistogramCounterResetHeader(t *testing.T) {
app := head.Appender(context.Background()) app := head.Appender(context.Background())
var err error var err error
if floatHisto { if floatHisto {
_, err = app.AppendHistogram(0, l, ts, nil, h.ToFloat()) _, err = app.AppendHistogram(0, l, ts, nil, h.ToFloat(nil))
} else { } else {
_, err = app.AppendHistogram(0, l, ts, h.Copy(), nil) _, err = app.AppendHistogram(0, l, ts, h.Copy(), nil)
} }

View file

@ -158,7 +158,7 @@ func TestRecord_EncodeDecode(t *testing.T) {
floatHistograms[i] = RefFloatHistogramSample{ floatHistograms[i] = RefFloatHistogramSample{
Ref: h.Ref, Ref: h.Ref,
T: h.T, T: h.T,
FH: h.H.ToFloat(), FH: h.H.ToFloat(nil),
} }
} }
decFloatHistograms, err := dec.FloatHistogramSamples(enc.FloatHistogramSamples(floatHistograms, nil), nil) decFloatHistograms, err := dec.FloatHistogramSamples(enc.FloatHistogramSamples(floatHistograms, nil), nil)

View file

@ -199,7 +199,7 @@ func TestTailSamples(t *testing.T) {
floatHistogram := enc.FloatHistogramSamples([]record.RefFloatHistogramSample{{ floatHistogram := enc.FloatHistogramSamples([]record.RefFloatHistogramSample{{
Ref: chunks.HeadSeriesRef(inner), Ref: chunks.HeadSeriesRef(inner),
T: now.UnixNano() + 1, T: now.UnixNano() + 1,
FH: hist.ToFloat(), FH: hist.ToFloat(nil),
}}, nil) }}, nil)
require.NoError(t, w.Log(floatHistogram)) require.NoError(t, w.Log(floatHistogram))
} }

View file

@ -138,7 +138,7 @@ Loop:
case chunkenc.ValFloat: case chunkenc.ValFloat:
f = sample.F() f = sample.F()
case chunkenc.ValHistogram: case chunkenc.ValHistogram:
fh = sample.H().ToFloat() fh = sample.H().ToFloat(nil)
case chunkenc.ValFloatHistogram: case chunkenc.ValFloatHistogram:
fh = sample.FH() fh = sample.FH()
default: default:

View file

@ -354,7 +354,7 @@ func TestFederationWithNativeHistograms(t *testing.T) {
_, err = app.AppendHistogram(0, l, 100*60*1000, histWithoutZeroBucket.Copy(), nil) _, err = app.AppendHistogram(0, l, 100*60*1000, histWithoutZeroBucket.Copy(), nil)
expVec = append(expVec, promql.Sample{ expVec = append(expVec, promql.Sample{
T: 100 * 60 * 1000, T: 100 * 60 * 1000,
H: histWithoutZeroBucket.ToFloat(), H: histWithoutZeroBucket.ToFloat(nil),
Metric: expL, Metric: expL,
}) })
default: default:
@ -363,7 +363,7 @@ func TestFederationWithNativeHistograms(t *testing.T) {
_, err = app.AppendHistogram(0, l, 100*60*1000, hist.Copy(), nil) _, err = app.AppendHistogram(0, l, 100*60*1000, hist.Copy(), nil)
expVec = append(expVec, promql.Sample{ expVec = append(expVec, promql.Sample{
T: 100 * 60 * 1000, T: 100 * 60 * 1000,
H: hist.ToFloat(), H: hist.ToFloat(nil),
Metric: expL, Metric: expL,
}) })
} }