diff --git a/promql/engine.go b/promql/engine.go index 4fa2a513be..8b49879217 100644 --- a/promql/engine.go +++ b/promql/engine.go @@ -2078,21 +2078,27 @@ loop: case chunkenc.ValNone: break loop case chunkenc.ValFloatHistogram, chunkenc.ValHistogram: - t, h := buf.AtFloatHistogram() - if value.IsStaleNaN(h.Sum) { - continue loop - } + t := buf.AtT() // Values in the buffer are guaranteed to be smaller than maxt. if t >= mintHistograms { - if ev.currentSamples >= ev.maxSamples { - ev.error(ErrTooManySamples(env)) - } - point := HPoint{T: t, H: h} if histograms == nil { histograms = getHPointSlice(16) } - histograms = append(histograms, point) - ev.currentSamples += point.size() + n := len(histograms) + if n < cap(histograms) { + histograms = histograms[:n+1] + } else { + histograms = append(histograms, HPoint{}) + } + histograms[n].T, histograms[n].H = buf.AtFloatHistogram(histograms[n].H) + if value.IsStaleNaN(histograms[n].H.Sum) { + histograms = histograms[:n] + continue loop + } + if ev.currentSamples >= ev.maxSamples { + ev.error(ErrTooManySamples(env)) + } + ev.currentSamples += histograms[n].size() } case chunkenc.ValFloat: t, f := buf.At() @@ -2108,7 +2114,12 @@ loop: if floats == nil { floats = getFPointSlice(16) } - floats = append(floats, FPoint{T: t, F: f}) + if n := len(floats); n < cap(floats) { + floats = floats[:n+1] + floats[n].T, floats[n].F = t, f + } else { + floats = append(floats, FPoint{T: t, F: f}) + } } } } diff --git a/storage/buffer.go b/storage/buffer.go index f686796caf..49dfbd2999 100644 --- a/storage/buffer.go +++ b/storage/buffer.go @@ -74,7 +74,7 @@ func (b *BufferedSeriesIterator) PeekBack(n int) (sample chunks.Sample, ok bool) // Buffer returns an iterator over the buffered data. Invalidates previously // returned iterators. -func (b *BufferedSeriesIterator) Buffer() chunkenc.Iterator { +func (b *BufferedSeriesIterator) Buffer() *sampleRingIterator { return b.buf.iterator() } @@ -304,7 +304,7 @@ func (r *sampleRing) reset() { } // Returns the current iterator. Invalidates previously returned iterators. -func (r *sampleRing) iterator() chunkenc.Iterator { +func (r *sampleRing) iterator() *sampleRingIterator { r.it.r = r r.it.i = -1 return &r.it @@ -374,9 +374,9 @@ func (it *sampleRingIterator) AtHistogram() (int64, *histogram.Histogram) { return it.t, it.h } -func (it *sampleRingIterator) AtFloatHistogram() (int64, *histogram.FloatHistogram) { +func (it *sampleRingIterator) AtFloatHistogram(fh *histogram.FloatHistogram) (int64, *histogram.FloatHistogram) { if it.fh == nil { - return it.t, it.h.ToFloat(nil) + return it.t, it.h.ToFloat(fh) } return it.t, it.fh } diff --git a/storage/buffer_test.go b/storage/buffer_test.go index 84f94a008f..12e6ff0f05 100644 --- a/storage/buffer_test.go +++ b/storage/buffer_test.go @@ -243,11 +243,11 @@ func TestBufferedSeriesIteratorMixedHistograms(t *testing.T) { buf := it.Buffer() require.Equal(t, chunkenc.ValFloatHistogram, buf.Next()) - _, fh := buf.AtFloatHistogram() + _, fh := buf.AtFloatHistogram(nil) require.Equal(t, histograms[0].ToFloat(nil), fh) require.Equal(t, chunkenc.ValHistogram, buf.Next()) - _, fh = buf.AtFloatHistogram() + _, fh = buf.AtFloatHistogram(nil) require.Equal(t, histograms[1].ToFloat(nil), fh) }