Skip to content

Commit fcb1a31

Browse files
committed
slog: internal/buffer
The internal/buffer package provides a pool-allocated byte buffer. Change-Id: I85da789afbb93ca78ac8b0387f4bf0fc16663faf Reviewed-on: https://go-review.googlesource.com/c/exp/+/426022 Reviewed-by: Alan Donovan <[email protected]> Run-TryBot: Jonathan Amsterdam <[email protected]> TryBot-Result: Gopher Robot <[email protected]>
1 parent d43d523 commit fcb1a31

File tree

2 files changed

+76
-0
lines changed

2 files changed

+76
-0
lines changed

slog/internal/buffer/buffer.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright 2022 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// Package buffer provides a pool-allocated byte buffer.
6+
package buffer
7+
8+
import (
9+
"sync"
10+
)
11+
12+
// buffer adapted from go/src/fmt/print.go
13+
type Buffer []byte
14+
15+
// Having an initial size gives a dramatic speedup.
16+
var bufPool = sync.Pool{
17+
New: func() any {
18+
b := make([]byte, 0, 1024)
19+
return (*Buffer)(&b)
20+
},
21+
}
22+
23+
func New() *Buffer {
24+
return bufPool.Get().(*Buffer)
25+
}
26+
27+
func (b *Buffer) Free() {
28+
// To reduce peak allocation, return only smaller buffers to the pool.
29+
const maxBufferSize = 16 << 10
30+
if cap(*b) <= maxBufferSize {
31+
*b = (*b)[:0]
32+
bufPool.Put(b)
33+
}
34+
}
35+
func (b *Buffer) Write(p []byte) {
36+
*b = append(*b, p...)
37+
}
38+
39+
func (b *Buffer) WriteString(s string) {
40+
*b = append(*b, s...)
41+
}
42+
43+
func (b *Buffer) WriteByte(c byte) {
44+
*b = append(*b, c)
45+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright 2022 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package buffer
6+
7+
import "testing"
8+
9+
func Test(t *testing.T) {
10+
b := New()
11+
defer b.Free()
12+
b.WriteString("hello")
13+
b.WriteByte(',')
14+
b.Write([]byte(" world"))
15+
got := string(*b)
16+
want := "hello, world"
17+
if got != want {
18+
t.Errorf("got %q, want %q", got, want)
19+
}
20+
}
21+
22+
func TestAlloc(t *testing.T) {
23+
got := int(testing.AllocsPerRun(5, func() {
24+
b := New()
25+
defer b.Free()
26+
b.WriteString("not 1K worth of bytes")
27+
}))
28+
if got != 0 {
29+
t.Errorf("got %d allocs, want 0", got)
30+
}
31+
}

0 commit comments

Comments
 (0)