logtail: reduce allocations encoding text

Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
reviewable/pr253/r1
Brad Fitzpatrick 4 years ago committed by Brad Fitzpatrick
parent 2863e49db9
commit fcb6a34f4b

@ -334,10 +334,22 @@ func (l *logger) send(jsonBlob []byte) (int, error) {
return n, err
}
// TODO: instead of allocating, this should probably just append
// directly into the output log buffer.
func (l *logger) encodeText(buf []byte, skipClientTime bool) []byte {
now := l.timeNow()
b := make([]byte, 0, len(buf)+16)
// Factor in JSON encoding overhead to try to only do one alloc
// in the make below (so appends don't resize the buffer).
overhead := 13
if !skipClientTime {
overhead += 67
}
// TODO: do a pass over buf and count how many backslashes will be needed?
// For now just factor in a dozen.
overhead += 12
b := make([]byte, 0, len(buf)+overhead)
b = append(b, '{')
if !skipClientTime {
@ -364,9 +376,14 @@ func (l *logger) encodeText(buf []byte, skipClientTime bool) []byte {
case '\\':
b = append(b, '\\', '\\')
default:
// TODO: what about binary gibberish or non UTF-8?
b = append(b, c)
}
if l.lowMem && i > 254 {
// TODO: this can break a UTF-8 character
// mid-encoding. We don't tend to log
// non-ASCII stuff ourselves, but e.g. client
// names might be.
b = append(b, "…"...)
break
}

@ -7,6 +7,7 @@ package logtail
import (
"context"
"testing"
"time"
)
func TestFastShutdown(t *testing.T) {
@ -18,3 +19,16 @@ func TestFastShutdown(t *testing.T) {
})
l.Shutdown(ctx)
}
var sink []byte
func TestLoggerEncodeTextAllocs(t *testing.T) {
lg := &logger{timeNow: time.Now}
inBuf := []byte("some text to encode")
n := testing.AllocsPerRun(1000, func() {
sink = lg.encodeText(inBuf, false)
})
if int(n) != 1 {
t.Logf("allocs = %d; want 1", int(n))
}
}

Loading…
Cancel
Save