[PERF] TSDB: Optimize appender creation on empty chunks (#16922)

Skip creating an iterator and walking all through any existing values,
when we can easily tell there are no existing values.

This is the normal case - the TSDB head creates an appender immediately
after creating every chunk.

Remove redundant handling of empty chunks.

Signed-off-by: Bryan Boreham <bjboreham@gmail.com>
This commit is contained in:
Bryan Boreham 2025-08-27 17:11:08 +01:00 committed by GitHub
parent 4a782634a4
commit 2fb50b12cd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 9 additions and 11 deletions

View File

@ -89,6 +89,9 @@ func (c *FloatHistogramChunk) Compact() {
// Appender implements the Chunk interface.
func (c *FloatHistogramChunk) Appender() (Appender, error) {
if len(c.b.stream) == 3 { // Avoid allocating an Iterator when chunk is empty.
return &FloatHistogramAppender{b: &c.b, t: math.MinInt64, sum: xorValue{leading: 0xff}, cnt: xorValue{leading: 0xff}, zCnt: xorValue{leading: 0xff}}, nil
}
it := c.iterator(nil)
// To get an appender, we must know the state it would have if we had
@ -133,11 +136,6 @@ func (c *FloatHistogramChunk) Appender() (Appender, error) {
nBuckets: nBuckets,
sum: it.sum,
}
if it.numTotal == 0 {
a.sum.leading = 0xff
a.cnt.leading = 0xff
a.zCnt.leading = 0xff
}
return a, nil
}

View File

@ -100,6 +100,9 @@ func (c *HistogramChunk) Compact() {
// Appender implements the Chunk interface.
func (c *HistogramChunk) Appender() (Appender, error) {
if len(c.b.stream) == 3 { // Avoid allocating an Iterator when chunk is empty.
return &HistogramAppender{b: &c.b, t: math.MinInt64, leading: 0xff}, nil
}
it := c.iterator(nil)
// To get an appender, we must know the state it would have if we had
@ -134,9 +137,6 @@ func (c *HistogramChunk) Appender() (Appender, error) {
leading: it.leading,
trailing: it.trailing,
}
if it.numTotal == 0 {
a.leading = 0xff
}
return a, nil
}

View File

@ -98,6 +98,9 @@ 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) {
if len(c.b.stream) == 2 { // Avoid allocating an Iterator when chunk is empty.
return &xorAppender{b: &c.b, t: math.MinInt64, leading: 0xff}, nil
}
it := c.iterator(nil)
// To get an appender we must know the state it would have if we had
@ -117,9 +120,6 @@ func (c *XORChunk) Appender() (Appender, error) {
leading: it.leading,
trailing: it.trailing,
}
if it.numTotal == 0 {
a.leading = 0xff
}
return a, nil
}