tsdb/chunkenc: add writeBits benchmarks, clarify comments, and simplify encodeJoint

Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com>
This commit is contained in:
Julien Pivotto 2026-03-20 13:42:03 +01:00
parent e865bdd172
commit 3b2b42f681
3 changed files with 49 additions and 8 deletions

View File

@ -101,6 +101,7 @@ func (b *bstream) writeByte(byt byte) {
// writeBits writes the nbits right-most bits of u to the stream
// in left-to-right order.
// TODO: Once XOR2 stabilizes, replace writeBits with the writeBitsFast implementation and remove writeBitsFast.
func (b *bstream) writeBits(u uint64, nbits int) {
u <<= 64 - uint(nbits)
for nbits >= 8 {
@ -368,9 +369,8 @@ func (b *bstreamReader) readXOR2Control() (uint8, error) {
}
// readUvarint decodes a varint-encoded uint64 using direct method calls,
// avoiding the io.ByteReader interface dispatch used by binary.ReadUvarint.
// This prevents interior pointer references on goroutine stacks that the GC
// must trace via findObject, reducing GC overhead.
// avoiding the io.ByteReader interface dispatch used by binary.ReadUvarint,
// which causes the receiver to escape to the heap.
func (b *bstreamReader) readUvarint() (uint64, error) {
var x uint64
var s uint
@ -389,7 +389,8 @@ func (b *bstreamReader) readUvarint() (uint64, error) {
}
// readVarint decodes a varint-encoded int64 using direct method calls,
// avoiding the io.ByteReader interface dispatch used by binary.ReadVarint.
// avoiding the io.ByteReader interface dispatch used by binary.ReadVarint,
// which causes the receiver to escape to the heap.
func (b *bstreamReader) readVarint() (int64, error) {
ux, err := b.readUvarint()
x := int64(ux >> 1)

View File

@ -14,6 +14,7 @@
package chunkenc
import (
"fmt"
"testing"
"github.com/stretchr/testify/require"
@ -32,6 +33,44 @@ func TestBstream_Reset(t *testing.T) {
}, bs)
}
// BenchmarkWriteBits benchmarks writeBits for various bit widths.
func BenchmarkWriteBits(b *testing.B) {
sizes := []int{1, 8, 17, 32, 52, 64}
for _, nbits := range sizes {
b.Run(fmt.Sprintf("nbits=%d", nbits), func(b *testing.B) {
b.ReportAllocs()
var bs bstream
bs.stream = make([]byte, 0, 1024)
for range b.N {
bs.stream = bs.stream[:0]
bs.count = 0
for j := range 100 {
bs.writeBits(uint64(j), nbits)
}
}
})
}
}
// BenchmarkWriteBitsFast benchmarks writeBitsFast for various bit widths.
func BenchmarkWriteBitsFast(b *testing.B) {
sizes := []int{1, 8, 17, 32, 52, 64}
for _, nbits := range sizes {
b.Run(fmt.Sprintf("nbits=%d", nbits), func(b *testing.B) {
b.ReportAllocs()
var bs bstream
bs.stream = make([]byte, 0, 1024)
for range b.N {
bs.stream = bs.stream[:0]
bs.count = 0
for j := range 100 {
bs.writeBitsFast(uint64(j), nbits)
}
}
})
}
}
func TestBstreamReader(t *testing.T) {
// Write to the bit stream.
w := bstream{}

View File

@ -304,12 +304,13 @@ func (a *xor2Appender) encodeJoint(dod int64, v float64) {
a.b.writeBitsFast(0b11111, 5)
return
}
if vbits := math.Float64bits(v) ^ math.Float64bits(a.v); vbits == 0 {
vbits := math.Float64bits(v) ^ math.Float64bits(a.v)
if vbits == 0 {
a.b.writeBit(zero)
} else {
a.b.writeBitsFast(0b10, 2)
a.writeVDeltaKnownNonZero(vbits)
return
}
a.b.writeBitsFast(0b10, 2)
a.writeVDeltaKnownNonZero(vbits)
return
}