diff --git a/tsdb/chunkenc/float_histogram.go b/tsdb/chunkenc/float_histogram.go index 7f3b2a5968..4c66c39503 100644 --- a/tsdb/chunkenc/float_histogram.go +++ b/tsdb/chunkenc/float_histogram.go @@ -18,11 +18,20 @@ import ( "errors" "fmt" "math" + "sync" "github.com/prometheus/prometheus/model/histogram" "github.com/prometheus/prometheus/model/value" ) +// floatHistogramChunkAppenderIterPool is exclusively used in Appender() to help reduce +// allocations under heavy usage. +var floatHistogramChunkAppenderIterPool = sync.Pool{ + New: func() interface{} { + return &floatHistogramIterator{} + }, +} + // FloatHistogramChunk holds encoded sample data for a sparse, high-resolution // float histogram. // @@ -104,7 +113,8 @@ func (c *FloatHistogramChunk) Compact() { // Appender implements the Chunk interface. func (c *FloatHistogramChunk) Appender() (Appender, error) { - it := c.iterator(nil) + it := c.iterator(floatHistogramChunkAppenderIterPool.Get().(*floatHistogramIterator)) + defer floatHistogramChunkAppenderIterPool.Put(it) // To get an appender, we must know the state it would have if we had // appended all existing data from scratch. We iterate through the end diff --git a/tsdb/chunkenc/histogram.go b/tsdb/chunkenc/histogram.go index 4ba0c467d8..566e9887e7 100644 --- a/tsdb/chunkenc/histogram.go +++ b/tsdb/chunkenc/histogram.go @@ -18,11 +18,20 @@ import ( "errors" "fmt" "math" + "sync" "github.com/prometheus/prometheus/model/histogram" "github.com/prometheus/prometheus/model/value" ) +// histogramChunkAppenderIterPool is exclusively used in Appender() to help reduce +// allocations under heavy usage. +var histogramChunkAppenderIterPool = sync.Pool{ + New: func() interface{} { + return &histogramIterator{} + }, +} + // HistogramChunk holds encoded sample data for a sparse, high-resolution // histogram. // @@ -115,7 +124,8 @@ func (c *HistogramChunk) Compact() { // Appender implements the Chunk interface. func (c *HistogramChunk) Appender() (Appender, error) { - it := c.iterator(nil) + it := c.iterator(histogramChunkAppenderIterPool.Get().(*histogramIterator)) + defer histogramChunkAppenderIterPool.Put(it) // To get an appender, we must know the state it would have if we had // appended all existing data from scratch. We iterate through the end diff --git a/tsdb/chunkenc/xor.go b/tsdb/chunkenc/xor.go index ac75a5994b..db0ffd3a6d 100644 --- a/tsdb/chunkenc/xor.go +++ b/tsdb/chunkenc/xor.go @@ -47,6 +47,7 @@ import ( "encoding/binary" "math" "math/bits" + "sync" "github.com/prometheus/prometheus/model/histogram" ) @@ -55,6 +56,13 @@ const ( chunkCompactCapacityThreshold = 32 ) +// xorAppenderIterPool is exclusively used in Appender() to help reduce allocations under heavy usage. +var xorAppenderIterPool = sync.Pool{ + New: func() interface{} { + return &xorIterator{} + }, +} + // XORChunk holds XOR encoded sample data. type XORChunk struct { b bstream @@ -98,7 +106,8 @@ func (c *XORChunk) Compact() { // It is not valid to call Appender() multiple times concurrently or to use multiple // Appenders on the same chunk. func (c *XORChunk) Appender() (Appender, error) { - it := c.iterator(nil) + it := c.iterator(xorAppenderIterPool.Get().(*xorIterator)) + defer xorAppenderIterPool.Put(it) // To get an appender we must know the state it would have if we had // appended all existing data from scratch.