bench
This commit is contained in:
parent
49f465619d
commit
a921d02997
@ -22,7 +22,7 @@ func TestContent(t *testing.T) {
|
||||
return n, nil
|
||||
})
|
||||
|
||||
p := &pool{allocSize: 2}
|
||||
p := &fakePool{allocSize: 2}
|
||||
o := buffer.Options{Pool: p}
|
||||
r := buffer.BufferedContent(c, o)
|
||||
b := make([]byte, 3)
|
||||
@ -48,7 +48,7 @@ func TestContent(t *testing.T) {
|
||||
return 0, nil
|
||||
})
|
||||
|
||||
p := &pool{allocSize: 2}
|
||||
p := &fakePool{allocSize: 2}
|
||||
o := buffer.Options{Pool: p}
|
||||
r := buffer.BufferedContent(c, o)
|
||||
b := make([]byte, 3)
|
||||
@ -72,7 +72,7 @@ func TestContent(t *testing.T) {
|
||||
return n, errTest
|
||||
})
|
||||
|
||||
p := &pool{allocSize: 2}
|
||||
p := &fakePool{allocSize: 2}
|
||||
o := buffer.Options{Pool: p}
|
||||
r := buffer.BufferedContent(c, o)
|
||||
b := make([]byte, 3)
|
||||
@ -98,7 +98,7 @@ func TestContent(t *testing.T) {
|
||||
return 0, errTest
|
||||
})
|
||||
|
||||
p := &pool{allocSize: 2}
|
||||
p := &fakePool{allocSize: 2}
|
||||
o := buffer.Options{Pool: p}
|
||||
r := buffer.BufferedContent(c, o)
|
||||
b := make([]byte, 3)
|
||||
@ -122,7 +122,7 @@ func TestContent(t *testing.T) {
|
||||
return n, nil
|
||||
})
|
||||
|
||||
p := &pool{
|
||||
p := &fakePool{
|
||||
allocSize: 2,
|
||||
errAfter: []int{1},
|
||||
}
|
||||
@ -154,7 +154,7 @@ func TestContent(t *testing.T) {
|
||||
return n, nil
|
||||
})
|
||||
|
||||
p := &pool{
|
||||
p := &fakePool{
|
||||
allocSize: 2,
|
||||
errAfter: []int{0},
|
||||
}
|
||||
@ -175,7 +175,7 @@ func TestContent(t *testing.T) {
|
||||
return 0, nil
|
||||
})
|
||||
|
||||
p := &pool{
|
||||
p := &fakePool{
|
||||
allocSize: 2,
|
||||
errAfter: []int{1},
|
||||
}
|
||||
@ -202,7 +202,7 @@ func TestContent(t *testing.T) {
|
||||
return 0, nil
|
||||
})
|
||||
|
||||
p := &pool{allocSize: 2}
|
||||
p := &fakePool{allocSize: 2}
|
||||
o := buffer.Options{Pool: p}
|
||||
r := buffer.BufferedContent(c, o)
|
||||
b := make([]byte, 3)
|
||||
@ -232,7 +232,7 @@ func TestContent(t *testing.T) {
|
||||
return 0, nil
|
||||
})
|
||||
|
||||
p := &pool{allocSize: 2}
|
||||
p := &fakePool{allocSize: 2}
|
||||
o := buffer.Options{Pool: p}
|
||||
r := buffer.BufferedContent(c, o)
|
||||
b := make([]byte, 3)
|
||||
@ -267,7 +267,7 @@ func TestContent(t *testing.T) {
|
||||
return n, errTest
|
||||
})
|
||||
|
||||
p := &pool{allocSize: 3}
|
||||
p := &fakePool{allocSize: 3}
|
||||
o := buffer.Options{Pool: p}
|
||||
r := buffer.BufferedContent(c, o)
|
||||
b := make([]byte, 3)
|
||||
@ -296,7 +296,7 @@ func TestContent(t *testing.T) {
|
||||
return 0, errTest2
|
||||
})
|
||||
|
||||
p := &pool{
|
||||
p := &fakePool{
|
||||
allocSize: 2,
|
||||
errAfter: []int{1},
|
||||
}
|
||||
|
||||
6
lib.go
6
lib.go
@ -59,7 +59,7 @@ var (
|
||||
// DefultPool initializes a synchronized pool that stores and returns byte slices of allocSize length. It can be
|
||||
// used with multiple readers concurrently.
|
||||
func DefaultPool(allocSize int) Pool {
|
||||
if allocSize == 0 {
|
||||
if allocSize <= 0 {
|
||||
allocSize = 1 << 12
|
||||
}
|
||||
|
||||
@ -68,6 +68,10 @@ func DefaultPool(allocSize int) Pool {
|
||||
|
||||
// NoPool returns a noop pool.
|
||||
func NoPool(allocSize int) Pool {
|
||||
if allocSize <= 0 {
|
||||
allocSize = 1 << 12
|
||||
}
|
||||
|
||||
return noPool{allocSize: allocSize}
|
||||
}
|
||||
|
||||
|
||||
186
lib_test.go
186
lib_test.go
@ -6,7 +6,6 @@ import (
|
||||
"code.squareroundforest.org/arpio/buffer"
|
||||
"errors"
|
||||
"io"
|
||||
"runtime"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@ -172,57 +171,32 @@ func (w writerOnly) Write(p []byte) (int, error) {
|
||||
}
|
||||
|
||||
func TestBenchmarkThroughput(t *testing.T) {
|
||||
p := buffer.DefaultPool(0)
|
||||
p := buffer.NoPool(0)
|
||||
dst := bytes.NewBuffer(nil)
|
||||
wo := writerOnly{dst}
|
||||
src := &gen{max: 1 << 18}
|
||||
r := buffer.BufferedReader(src, buffer.Options{Pool: p})
|
||||
ro := readerOnly{r}
|
||||
dst.Reset()
|
||||
if n, err := io.Copy(wo, ro); n != 1<<18 || err != nil {
|
||||
n, err := io.Copy(wo, ro)
|
||||
if n != 1<<18 || err != nil {
|
||||
t.Fatal(n, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBenchmarkCompare(t *testing.T) {
|
||||
func TestBenchmarkThroughputCompare(t *testing.T) {
|
||||
dst := bytes.NewBuffer(nil)
|
||||
wo := writerOnly{dst}
|
||||
src := &gen{max: 1 << 18}
|
||||
r := bufio.NewReader(src)
|
||||
ro := readerOnly{r}
|
||||
dst.Reset()
|
||||
if n, err := io.Copy(wo, ro); n != 1<<18 || err != nil {
|
||||
t.Fatal(n, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBenchmarkThroughputSTDLib(t *testing.T) {
|
||||
p := buffer.DefaultPool(0)
|
||||
dst := bytes.NewBuffer(nil)
|
||||
wo := writerOnly{dst}
|
||||
src := bytes.NewBuffer(make([]byte, 1<<18))
|
||||
r := buffer.BufferedReader(src, buffer.Options{Pool: p})
|
||||
ro := readerOnly{r}
|
||||
dst.Reset()
|
||||
if n, err := io.Copy(wo, ro); n != 1<<18 || err != nil {
|
||||
t.Fatal(n, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBenchmarkCompareSTDLib(t *testing.T) {
|
||||
dst := bytes.NewBuffer(nil)
|
||||
wo := writerOnly{dst}
|
||||
src := bytes.NewBuffer(make([]byte, 1<<18))
|
||||
r := bufio.NewReader(src)
|
||||
ro := readerOnly{r}
|
||||
dst.Reset()
|
||||
if n, err := io.Copy(wo, ro); n != 1<<18 || err != nil {
|
||||
n, err := io.Copy(wo, ro)
|
||||
if n != 1<<18 || err != nil {
|
||||
t.Fatal(n, err)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkThroughput(b *testing.B) {
|
||||
p := buffer.DefaultPool(0)
|
||||
p := buffer.NoPool(0)
|
||||
dst := bytes.NewBuffer(nil)
|
||||
wo := writerOnly{dst}
|
||||
for i := 0; i < b.N; i++ {
|
||||
@ -234,7 +208,7 @@ func BenchmarkThroughput(b *testing.B) {
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkCompare(b *testing.B) {
|
||||
func BenchmarkThroughputCompare(b *testing.B) {
|
||||
dst := bytes.NewBuffer(nil)
|
||||
wo := writerOnly{dst}
|
||||
for i := 0; i < b.N; i++ {
|
||||
@ -246,58 +220,128 @@ func BenchmarkCompare(b *testing.B) {
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkThroughputP(b *testing.B) {
|
||||
p := buffer.DefaultPool(0)
|
||||
b.SetParallelism(runtime.GOMAXPROCS(-1) * 64)
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
func TestThroughputPooled(t *testing.T) {
|
||||
p := &foreverPool{allocSize: 1 << 12}
|
||||
dst := bytes.NewBuffer(nil)
|
||||
wo := writerOnly{dst}
|
||||
for pb.Next() {
|
||||
src := &gen{max: 1 << 18}
|
||||
r := buffer.BufferedReader(src, buffer.Options{Pool: p})
|
||||
ro := readerOnly{r}
|
||||
n, err := io.Copy(wo, ro)
|
||||
if n != 1<<18 || err != nil {
|
||||
t.Fatal(n, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestThroughputPooledCompare(t *testing.T) {
|
||||
dst := bytes.NewBuffer(nil)
|
||||
wo := writerOnly{dst}
|
||||
r := bufio.NewReader(nil)
|
||||
src := &gen{max: 1 << 18}
|
||||
r.Reset(src)
|
||||
ro := readerOnly{r}
|
||||
n, err := io.Copy(wo, ro)
|
||||
if n != 1<<18 || err != nil {
|
||||
t.Fatal(n, err)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkThroughputPooled(b *testing.B) {
|
||||
p := &foreverPool{allocSize: 1 << 12}
|
||||
dst := bytes.NewBuffer(nil)
|
||||
wo := writerOnly{dst}
|
||||
for i := 0; i < b.N; i++ {
|
||||
src := &gen{max: 1 << 18}
|
||||
r := buffer.BufferedReader(src, buffer.Options{Pool: p})
|
||||
ro := readerOnly{r}
|
||||
dst.Reset()
|
||||
io.Copy(wo, ro)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkThroughputPooledCompare(b *testing.B) {
|
||||
dst := bytes.NewBuffer(nil)
|
||||
wo := writerOnly{dst}
|
||||
r := bufio.NewReader(nil)
|
||||
for i := 0; i < b.N; i++ {
|
||||
src := &gen{max: 1 << 18}
|
||||
r.Reset(src)
|
||||
ro := readerOnly{r}
|
||||
dst.Reset()
|
||||
io.Copy(wo, ro)
|
||||
}
|
||||
}
|
||||
|
||||
func TestThroughputPooledParallel(t *testing.T) {
|
||||
p := newSyncedForeverPool(func() []byte {
|
||||
return make([]byte, 1<<12)
|
||||
})
|
||||
|
||||
dst := bytes.NewBuffer(nil)
|
||||
wo := writerOnly{dst}
|
||||
src := &gen{max: 1 << 18}
|
||||
r := buffer.BufferedReader(src, buffer.Options{Pool: p})
|
||||
ro := readerOnly{r}
|
||||
n, err := io.Copy(wo, ro)
|
||||
if n != 1<<18 || err != nil {
|
||||
t.Fatal(n, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestThroughputPooledParallelCompare(t *testing.T) {
|
||||
p := newSyncedForeverPool(func() *bufio.Reader {
|
||||
return bufio.NewReader(nil)
|
||||
})
|
||||
|
||||
dst := bytes.NewBuffer(nil)
|
||||
wo := writerOnly{dst}
|
||||
r, err := p.Get()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
src := &gen{max: 1 << 18}
|
||||
r.Reset(src)
|
||||
ro := readerOnly{r}
|
||||
n, err := io.Copy(wo, ro)
|
||||
if n != 1<<18 || err != nil {
|
||||
t.Fatal(n, err)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkThroughputPooledParallel(b *testing.B) {
|
||||
p := newSyncedForeverPool(func() []byte {
|
||||
return make([]byte, 1<<12)
|
||||
})
|
||||
|
||||
b.ResetTimer()
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
src := &gen{max: 1 << 18}
|
||||
r := buffer.BufferedReader(src, buffer.Options{Pool: p})
|
||||
ro := readerOnly{r}
|
||||
dst := bytes.NewBuffer(nil)
|
||||
wo := writerOnly{dst}
|
||||
io.Copy(wo, ro)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkCompareP(b *testing.B) {
|
||||
b.SetParallelism(runtime.GOMAXPROCS(-1) * 64)
|
||||
func BenchmarkThroughputPooledParallelCompare(b *testing.B) {
|
||||
p := newSyncedForeverPool(func() *bufio.Reader {
|
||||
return bufio.NewReader(nil)
|
||||
})
|
||||
|
||||
b.ResetTimer()
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
r, _ := p.Get()
|
||||
src := &gen{max: 1 << 18}
|
||||
r.Reset(src)
|
||||
ro := readerOnly{r}
|
||||
dst := bytes.NewBuffer(nil)
|
||||
wo := writerOnly{dst}
|
||||
for pb.Next() {
|
||||
src := &gen{max: 1 << 18}
|
||||
r := bufio.NewReader(src)
|
||||
ro := readerOnly{r}
|
||||
dst.Reset()
|
||||
io.Copy(wo, ro)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkThroughputSTDLib(b *testing.B) {
|
||||
p := buffer.DefaultPool(0)
|
||||
dst := bytes.NewBuffer(nil)
|
||||
wo := writerOnly{dst}
|
||||
for i := 0; i < b.N; i++ {
|
||||
src := bytes.NewBuffer(make([]byte, 1<<18))
|
||||
r := buffer.BufferedReader(src, buffer.Options{Pool: p})
|
||||
ro := readerOnly{r}
|
||||
dst.Reset()
|
||||
io.Copy(wo, ro)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkCompareSTDLib(b *testing.B) {
|
||||
dst := bytes.NewBuffer(nil)
|
||||
wo := writerOnly{dst}
|
||||
for i := 0; i < b.N; i++ {
|
||||
src := bytes.NewBuffer(make([]byte, 1<<18))
|
||||
r := bufio.NewReader(src)
|
||||
ro := readerOnly{r}
|
||||
dst.Reset()
|
||||
io.Copy(wo, ro)
|
||||
}
|
||||
}
|
||||
|
||||
133
pool_test.go
133
pool_test.go
@ -9,7 +9,7 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
type pool struct {
|
||||
type fakePool struct {
|
||||
allocSize int
|
||||
alloc, free int
|
||||
errAfter []int
|
||||
@ -18,7 +18,17 @@ type pool struct {
|
||||
rand *rand.Rand
|
||||
}
|
||||
|
||||
func (p pool) allocCondition(c *[]int) bool {
|
||||
type foreverPool struct {
|
||||
allocSize int
|
||||
items [][]byte
|
||||
}
|
||||
|
||||
type syncedForeverPool[T any] struct {
|
||||
create func() T
|
||||
items chan []T
|
||||
}
|
||||
|
||||
func (p fakePool) allocCondition(c *[]int) bool {
|
||||
if len(*c) == 0 {
|
||||
return false
|
||||
}
|
||||
@ -31,7 +41,7 @@ func (p pool) allocCondition(c *[]int) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (p *pool) ensureRand() {
|
||||
func (p *fakePool) ensureRand() {
|
||||
if p.rand != nil {
|
||||
return
|
||||
}
|
||||
@ -39,7 +49,7 @@ func (p *pool) ensureRand() {
|
||||
p.rand = rand.New(rand.NewSource(9))
|
||||
}
|
||||
|
||||
func (p *pool) Get() ([]byte, error) {
|
||||
func (p *fakePool) Get() ([]byte, error) {
|
||||
defer func() {
|
||||
p.alloc++
|
||||
}()
|
||||
@ -66,16 +76,63 @@ func (p *pool) Get() ([]byte, error) {
|
||||
return make([]byte, n), nil
|
||||
}
|
||||
|
||||
func (p *pool) Put([]byte) {
|
||||
func (p *fakePool) Put([]byte) {
|
||||
p.free++
|
||||
}
|
||||
|
||||
func (p *foreverPool) Get() ([]byte, error) {
|
||||
if len(p.items) == 0 {
|
||||
return make([]byte, p.allocSize), nil
|
||||
}
|
||||
|
||||
var i []byte
|
||||
i, p.items = p.items[0], p.items[1:]
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (p *foreverPool) Put(i []byte) {
|
||||
p.items = append(p.items, i)
|
||||
}
|
||||
|
||||
func newSyncedForeverPool[T any](c func() T) *syncedForeverPool[T] {
|
||||
items := make(chan []T, 1)
|
||||
items <- nil
|
||||
return &syncedForeverPool[T]{
|
||||
create: c,
|
||||
items: items,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *syncedForeverPool[T]) Get() (T, error) {
|
||||
items := <-p.items
|
||||
defer func() {
|
||||
p.items <- items
|
||||
}()
|
||||
|
||||
if len(items) == 0 {
|
||||
return p.create(), nil
|
||||
}
|
||||
|
||||
var i T
|
||||
i, items = items[0], items[1:]
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (p *syncedForeverPool[T]) Put(i T) {
|
||||
items := <-p.items
|
||||
defer func() {
|
||||
p.items <- items
|
||||
}()
|
||||
|
||||
items = append(items, i)
|
||||
}
|
||||
|
||||
func TestPoolUsage(t *testing.T) {
|
||||
for _, cr := range []createReader{buffer.BufferedReader, testContent} {
|
||||
t.Run("allocate", func(t *testing.T) {
|
||||
t.Run("read", func(t *testing.T) {
|
||||
g := &gen{max: 1 << 15}
|
||||
p := &pool{allocSize: 1 << 12}
|
||||
p := &fakePool{allocSize: 1 << 12}
|
||||
o := buffer.Options{Pool: p}
|
||||
r := cr(g, o)
|
||||
b := make([]byte, 256)
|
||||
@ -99,7 +156,7 @@ func TestPoolUsage(t *testing.T) {
|
||||
|
||||
t.Run("read bytes", func(t *testing.T) {
|
||||
g := &gen{max: 1 << 15}
|
||||
p := &pool{allocSize: 1 << 9}
|
||||
p := &fakePool{allocSize: 1 << 9}
|
||||
o := buffer.Options{Pool: p}
|
||||
r := cr(g, o)
|
||||
b, ok, err := r.ReadBytes([]byte("123"), 1<<12)
|
||||
@ -122,7 +179,7 @@ func TestPoolUsage(t *testing.T) {
|
||||
|
||||
t.Run("read utf8", func(t *testing.T) {
|
||||
g := &gen{max: 1 << 15}
|
||||
p := &pool{allocSize: 1 << 12}
|
||||
p := &fakePool{allocSize: 1 << 12}
|
||||
o := buffer.Options{Pool: p}
|
||||
r := cr(g, o)
|
||||
runes, n, err := r.ReadUTF8(1 << 12)
|
||||
@ -145,7 +202,7 @@ func TestPoolUsage(t *testing.T) {
|
||||
|
||||
t.Run("peek", func(t *testing.T) {
|
||||
g := &gen{max: 1 << 15}
|
||||
p := &pool{allocSize: 1 << 12}
|
||||
p := &fakePool{allocSize: 1 << 12}
|
||||
o := buffer.Options{Pool: p}
|
||||
r := cr(g, o)
|
||||
b, err := r.Peek(3 * 1 << 12)
|
||||
@ -164,7 +221,7 @@ func TestPoolUsage(t *testing.T) {
|
||||
|
||||
t.Run("buffered", func(t *testing.T) {
|
||||
g := &gen{max: 1 << 15}
|
||||
p := &pool{allocSize: 1 << 12}
|
||||
p := &fakePool{allocSize: 1 << 12}
|
||||
o := buffer.Options{Pool: p}
|
||||
r := cr(g, o)
|
||||
b := r.Buffered()
|
||||
@ -179,7 +236,7 @@ func TestPoolUsage(t *testing.T) {
|
||||
|
||||
t.Run("write to", func(t *testing.T) {
|
||||
g := &gen{max: 1 << 15}
|
||||
p := &pool{allocSize: 1 << 12}
|
||||
p := &fakePool{allocSize: 1 << 12}
|
||||
o := buffer.Options{Pool: p}
|
||||
r := cr(g, o)
|
||||
|
||||
@ -206,7 +263,7 @@ func TestPoolUsage(t *testing.T) {
|
||||
t.Run("free", func(t *testing.T) {
|
||||
t.Run("read", func(t *testing.T) {
|
||||
g := &gen{max: 1 << 15}
|
||||
p := &pool{allocSize: 1 << 12}
|
||||
p := &fakePool{allocSize: 1 << 12}
|
||||
o := buffer.Options{Pool: p}
|
||||
r := cr(g, o)
|
||||
b := make([]byte, 1<<9)
|
||||
@ -232,7 +289,7 @@ func TestPoolUsage(t *testing.T) {
|
||||
|
||||
t.Run("read bytes", func(t *testing.T) {
|
||||
g := &gen{max: 1 << 15}
|
||||
p := &pool{allocSize: 1 << 12}
|
||||
p := &fakePool{allocSize: 1 << 12}
|
||||
o := buffer.Options{Pool: p}
|
||||
r := cr(g, o)
|
||||
_, _, err := r.ReadBytes([]byte("123"), 1<<15+3)
|
||||
@ -256,7 +313,7 @@ func TestPoolUsage(t *testing.T) {
|
||||
|
||||
t.Run("read utf8", func(t *testing.T) {
|
||||
g := &gen{max: 1 << 15}
|
||||
p := &pool{allocSize: 1 << 12}
|
||||
p := &fakePool{allocSize: 1 << 12}
|
||||
o := buffer.Options{Pool: p}
|
||||
r := cr(g, o)
|
||||
for {
|
||||
@ -285,7 +342,7 @@ func TestPoolUsage(t *testing.T) {
|
||||
|
||||
t.Run("peek", func(t *testing.T) {
|
||||
g := &gen{max: 1 << 15}
|
||||
p := &pool{allocSize: 1 << 12}
|
||||
p := &fakePool{allocSize: 1 << 12}
|
||||
o := buffer.Options{Pool: p}
|
||||
r := cr(g, o)
|
||||
b, err := r.Peek(3 * 1 << 12)
|
||||
@ -328,7 +385,7 @@ func TestPoolUsage(t *testing.T) {
|
||||
|
||||
t.Run("buffered", func(t *testing.T) {
|
||||
g := &gen{max: 1 << 15}
|
||||
p := &pool{allocSize: 1 << 12}
|
||||
p := &fakePool{allocSize: 1 << 12}
|
||||
o := buffer.Options{Pool: p}
|
||||
r := cr(g, o)
|
||||
b := r.Buffered()
|
||||
@ -343,7 +400,7 @@ func TestPoolUsage(t *testing.T) {
|
||||
|
||||
t.Run("write to", func(t *testing.T) {
|
||||
g := &gen{max: 1 << 15}
|
||||
p := &pool{allocSize: 1 << 12}
|
||||
p := &fakePool{allocSize: 1 << 12}
|
||||
o := buffer.Options{Pool: p}
|
||||
r := cr(g, o)
|
||||
|
||||
@ -374,7 +431,7 @@ func TestPoolUsage(t *testing.T) {
|
||||
t.Run("null segment", func(t *testing.T) {
|
||||
t.Run("read", func(t *testing.T) {
|
||||
g := &gen{max: 1 << 15}
|
||||
p := &pool{
|
||||
p := &fakePool{
|
||||
allocSize: 1 << 12,
|
||||
zeroAfter: []int{0},
|
||||
}
|
||||
@ -390,7 +447,7 @@ func TestPoolUsage(t *testing.T) {
|
||||
|
||||
t.Run("read bytes", func(t *testing.T) {
|
||||
g := &gen{max: 1 << 15}
|
||||
p := &pool{
|
||||
p := &fakePool{
|
||||
allocSize: 1 << 9,
|
||||
zeroAfter: []int{1},
|
||||
}
|
||||
@ -410,7 +467,7 @@ func TestPoolUsage(t *testing.T) {
|
||||
|
||||
t.Run("read utf8", func(t *testing.T) {
|
||||
g := &gen{max: 1 << 15}
|
||||
p := &pool{
|
||||
p := &fakePool{
|
||||
allocSize: 1 << 12,
|
||||
zeroAfter: []int{0},
|
||||
}
|
||||
@ -425,7 +482,7 @@ func TestPoolUsage(t *testing.T) {
|
||||
|
||||
t.Run("peek", func(t *testing.T) {
|
||||
g := &gen{max: 1 << 15}
|
||||
p := &pool{
|
||||
p := &fakePool{
|
||||
allocSize: 1 << 12,
|
||||
zeroAfter: []int{0},
|
||||
}
|
||||
@ -440,7 +497,7 @@ func TestPoolUsage(t *testing.T) {
|
||||
|
||||
t.Run("write to", func(t *testing.T) {
|
||||
g := &gen{max: 1 << 15}
|
||||
p := &pool{
|
||||
p := &fakePool{
|
||||
allocSize: 1 << 12,
|
||||
zeroAfter: []int{0},
|
||||
}
|
||||
@ -465,7 +522,7 @@ func TestPoolUsage(t *testing.T) {
|
||||
customContent: map[int][]byte{1 << 11: []byte("123")},
|
||||
}
|
||||
|
||||
p := &pool{varyingSize: []int{8, 256}}
|
||||
p := &fakePool{varyingSize: []int{8, 256}}
|
||||
o := buffer.Options{Pool: p}
|
||||
r := cr(g, o)
|
||||
b, ok, err := r.ReadBytes([]byte("123"), 1<<15)
|
||||
@ -484,7 +541,7 @@ func TestPoolUsage(t *testing.T) {
|
||||
|
||||
t.Run("find not", func(t *testing.T) {
|
||||
g := &gen{max: 1 << 15}
|
||||
p := &pool{varyingSize: []int{8, 256}}
|
||||
p := &fakePool{varyingSize: []int{8, 256}}
|
||||
o := buffer.Options{Pool: p}
|
||||
r := cr(g, o)
|
||||
b, ok, err := r.ReadBytes([]byte("123"), 1<<15)
|
||||
@ -504,7 +561,7 @@ func TestPoolUsage(t *testing.T) {
|
||||
|
||||
t.Run("peek", func(t *testing.T) {
|
||||
g := &gen{max: 1 << 15}
|
||||
p := &pool{varyingSize: []int{8, 256}}
|
||||
p := &fakePool{varyingSize: []int{8, 256}}
|
||||
o := buffer.Options{Pool: p}
|
||||
r := cr(g, o)
|
||||
b, err := r.Peek(1 << 11)
|
||||
@ -521,7 +578,7 @@ func TestPoolUsage(t *testing.T) {
|
||||
t.Run("one byte segments", func(t *testing.T) {
|
||||
t.Run("read", func(t *testing.T) {
|
||||
g := &gen{max: 1 << 15}
|
||||
p := &pool{allocSize: 1}
|
||||
p := &fakePool{allocSize: 1}
|
||||
o := buffer.Options{Pool: p}
|
||||
r := cr(g, o)
|
||||
b, err := io.ReadAll(r)
|
||||
@ -542,7 +599,7 @@ func TestPoolUsage(t *testing.T) {
|
||||
customContent: map[int][]byte{1 << 11: []byte("123")},
|
||||
}
|
||||
|
||||
p := &pool{allocSize: 1}
|
||||
p := &fakePool{allocSize: 1}
|
||||
o := buffer.Options{Pool: p}
|
||||
r := cr(g, o)
|
||||
b, ok, err := r.ReadBytes([]byte("123"), 1<<15)
|
||||
@ -561,7 +618,7 @@ func TestPoolUsage(t *testing.T) {
|
||||
|
||||
t.Run("find not", func(t *testing.T) {
|
||||
g := &gen{max: 1 << 15}
|
||||
p := &pool{allocSize: 1}
|
||||
p := &fakePool{allocSize: 1}
|
||||
o := buffer.Options{Pool: p}
|
||||
r := cr(g, o)
|
||||
b, ok, err := r.ReadBytes([]byte("123"), 1<<15)
|
||||
@ -585,7 +642,7 @@ func TestPoolUsage(t *testing.T) {
|
||||
rng: utf8W2Range,
|
||||
}
|
||||
|
||||
p := &pool{allocSize: 1}
|
||||
p := &fakePool{allocSize: 1}
|
||||
o := buffer.Options{Pool: p}
|
||||
r := cr(g, o)
|
||||
runes, n, err := r.ReadUTF8(1 << 14)
|
||||
@ -604,7 +661,7 @@ func TestPoolUsage(t *testing.T) {
|
||||
|
||||
t.Run("peek", func(t *testing.T) {
|
||||
g := &gen{max: 1 << 15}
|
||||
p := &pool{allocSize: 1}
|
||||
p := &fakePool{allocSize: 1}
|
||||
o := buffer.Options{Pool: p}
|
||||
r := cr(g, o)
|
||||
b, err := r.Peek(1 << 14)
|
||||
@ -619,7 +676,7 @@ func TestPoolUsage(t *testing.T) {
|
||||
|
||||
t.Run("write to", func(t *testing.T) {
|
||||
g := &gen{max: 1 << 15}
|
||||
p := &pool{allocSize: 1}
|
||||
p := &fakePool{allocSize: 1}
|
||||
o := buffer.Options{Pool: p}
|
||||
r := cr(g, o)
|
||||
|
||||
@ -642,7 +699,7 @@ func TestPoolUsage(t *testing.T) {
|
||||
t.Run("pool error on allocate", func(t *testing.T) {
|
||||
t.Run("read", func(t *testing.T) {
|
||||
g := &gen{max: 1 << 15}
|
||||
p := &pool{
|
||||
p := &fakePool{
|
||||
allocSize: 1 << 11,
|
||||
errAfter: []int{0},
|
||||
}
|
||||
@ -662,7 +719,7 @@ func TestPoolUsage(t *testing.T) {
|
||||
t.Run("read bytes", func(t *testing.T) {
|
||||
t.Run("immediate", func(t *testing.T) {
|
||||
g := &gen{max: 1 << 15}
|
||||
p := &pool{
|
||||
p := &fakePool{
|
||||
allocSize: 1 << 11,
|
||||
errAfter: []int{0},
|
||||
}
|
||||
@ -685,7 +742,7 @@ func TestPoolUsage(t *testing.T) {
|
||||
|
||||
t.Run("on grow", func(t *testing.T) {
|
||||
g := &gen{max: 1 << 15}
|
||||
p := &pool{
|
||||
p := &fakePool{
|
||||
allocSize: 1 << 11,
|
||||
errAfter: []int{1},
|
||||
}
|
||||
@ -726,7 +783,7 @@ func TestPoolUsage(t *testing.T) {
|
||||
rng: utf8W2Range,
|
||||
}
|
||||
|
||||
p := &pool{
|
||||
p := &fakePool{
|
||||
allocSize: 1 << 11,
|
||||
errAfter: []int{0},
|
||||
}
|
||||
@ -750,7 +807,7 @@ func TestPoolUsage(t *testing.T) {
|
||||
t.Run("peek", func(t *testing.T) {
|
||||
t.Run("immediate", func(t *testing.T) {
|
||||
g := &gen{max: 1 << 15}
|
||||
p := &pool{
|
||||
p := &fakePool{
|
||||
allocSize: 1 << 11,
|
||||
errAfter: []int{0},
|
||||
}
|
||||
@ -769,7 +826,7 @@ func TestPoolUsage(t *testing.T) {
|
||||
|
||||
t.Run("on grow", func(t *testing.T) {
|
||||
g := &gen{max: 1 << 15}
|
||||
p := &pool{
|
||||
p := &fakePool{
|
||||
allocSize: 1 << 11,
|
||||
errAfter: []int{1},
|
||||
}
|
||||
@ -811,7 +868,7 @@ func TestPoolUsage(t *testing.T) {
|
||||
|
||||
t.Run("write to", func(t *testing.T) {
|
||||
g := &gen{max: 1 << 15}
|
||||
p := &pool{
|
||||
p := &fakePool{
|
||||
allocSize: 1 << 11,
|
||||
errAfter: []int{0},
|
||||
}
|
||||
|
||||
@ -437,6 +437,58 @@ func TestReadBytes(t *testing.T) {
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("single char delimiter", func(t *testing.T) {
|
||||
g := &gen{
|
||||
max: 1 << 15,
|
||||
customContentAfter: []int{12},
|
||||
customContent: map[int][]byte{12: []byte("1")},
|
||||
}
|
||||
|
||||
o := buffer.Options{Pool: buffer.NoPool(1 << 12)}
|
||||
r := cr(g, o)
|
||||
b, ok, err := r.ReadBytes([]byte{'1'}, 64)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !ok {
|
||||
t.Fatal("delimiter")
|
||||
}
|
||||
|
||||
if !bytes.Equal(b, append(generate(12), '1')) {
|
||||
t.Fatal("failed to generate right content")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("large delimiter", func(t *testing.T) {
|
||||
src := &gen{
|
||||
max: 1 << 18,
|
||||
customContentAfter: []int{1<<17 - 3},
|
||||
customContent: map[int][]byte{1<<17 - 3: []byte("123")},
|
||||
}
|
||||
|
||||
r := buffer.BufferedReader(src, buffer.Options{Pool: buffer.NoPool(1 << 12)})
|
||||
r.ReadBytes([]byte{'1'}, 1<<17+1<<16)
|
||||
})
|
||||
|
||||
t.Run("delimiter longer than content", func(t *testing.T) {
|
||||
g := &gen{max: 1 << 9}
|
||||
o := buffer.Options{Pool: buffer.NoPool(16)}
|
||||
r := cr(g, o)
|
||||
b, ok, err := r.ReadBytes(generate(1<<10), 1<<11)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if ok {
|
||||
t.Fatal("delimiter")
|
||||
}
|
||||
|
||||
if !bytes.Equal(b, generate(1<<9)) {
|
||||
t.Fatal("content")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("find not none consumed", func(t *testing.T) {
|
||||
g := &gen{}
|
||||
o := buffer.Options{Pool: buffer.NoPool(1 << 12)}
|
||||
|
||||
@ -225,8 +225,11 @@ func (r *reader) fillToDelimiter(delimiter []byte, max int) (int, bool) {
|
||||
m, c := match(d, r.segments[seg][first:last])
|
||||
if !m {
|
||||
i += 1 - len(delimiter) + len(d)
|
||||
seg, segStart = r.findSegmentDown(i)
|
||||
d = delimiter
|
||||
if i < r.len {
|
||||
seg, segStart = r.findSegmentDown(i)
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user