internal/encoder/json/fast/buffer.go

// Package fast holds micro-optimized encoding helpers that sit on the hot
// path of every log call. They are kept deliberately small so the inliner
// in the Go compiler can keep the call graph flat.
//
// See mercemay.top/src/lambdalog/ for broader context.
package fast

import (
	"strconv"
	"sync"
)

// defaultCapacity is the starting size of buffers in the pool. It is picked
// to be large enough to hold a typical single-line log record without any
// growth allocations.
const defaultCapacity = 512

// maxRetainedCapacity caps how large a pooled buffer may grow before it is
// discarded on Put. Without this, a single oversized record would poison the
// pool with a huge slice that wastes memory for subsequent small records.
const maxRetainedCapacity = 8 * 1024

// Buffer is an append-only byte buffer with a few numeric helpers. It is
// intentionally not a drop-in for bytes.Buffer: no Read, no grow-hooks.
type Buffer struct {
	b []byte
}

// Bytes returns the underlying slice. The returned value is only valid until
// the buffer is returned to the pool via Put.
func (b *Buffer) Bytes() []byte { return b.b }

// Len reports the number of bytes currently in the buffer.
func (b *Buffer) Len() int { return len(b.b) }

// Reset clears the buffer without freeing the underlying array.
func (b *Buffer) Reset() { b.b = b.b[:0] }

// AppendByte appends one byte.
func (b *Buffer) AppendByte(c byte) { b.b = append(b.b, c) }

// AppendString appends s.
func (b *Buffer) AppendString(s string) { b.b = append(b.b, s...) }

// AppendBytes appends p.
func (b *Buffer) AppendBytes(p []byte) { b.b = append(b.b, p...) }

// AppendInt appends a base-10 signed integer.
func AppendInt(b *Buffer, v int64) {
	b.b = strconv.AppendInt(b.b, v, 10)
}

// AppendUint appends a base-10 unsigned integer.
func AppendUint(b *Buffer, v uint64) {
	b.b = strconv.AppendUint(b.b, v, 10)
}

// AppendFloat appends f using the shortest representation. bitSize selects
// between float32/float64 formatting.
func AppendFloat(b *Buffer, f float64, bitSize int) {
	b.b = strconv.AppendFloat(b.b, f, 'g', -1, bitSize)
}

var pool = sync.Pool{
	New: func() any {
		return &Buffer{b: make([]byte, 0, defaultCapacity)}
	},
}

// Get pulls a Buffer from the pool with Reset already applied.
func Get() *Buffer {
	b := pool.Get().(*Buffer)
	b.Reset()
	return b
}

// Put returns b to the pool if it is within the retention cap. Callers must
// not reference b or its Bytes after calling Put.
func Put(b *Buffer) {
	if b == nil {
		return
	}
	if cap(b.b) > maxRetainedCapacity {
		return
	}
	pool.Put(b)
}