781 lines
16 KiB
Go
781 lines
16 KiB
Go
package buffer_test
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"code.squareroundforest.org/arpio/buffer"
|
|
"errors"
|
|
"io"
|
|
"testing"
|
|
)
|
|
|
|
func TestLib(t *testing.T) {
|
|
t.Run("default pool", func(t *testing.T) {
|
|
t.Run("buffered reader", func(t *testing.T) {
|
|
g := &gen{max: 1 << 18}
|
|
r := buffer.BufferedReader(g, buffer.Options{})
|
|
b, err := io.ReadAll(r)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if !bytes.Equal(b, generate(1<<18)) {
|
|
t.Fatal("output does not match", len(b))
|
|
}
|
|
})
|
|
|
|
t.Run("buffered content", func(t *testing.T) {
|
|
c := buffer.ContentFunc(func(w io.Writer) (int64, error) {
|
|
g := &gen{max: 1 << 18}
|
|
return io.Copy(w, g)
|
|
})
|
|
|
|
r := buffer.BufferedContent(c, buffer.Options{})
|
|
b, err := io.ReadAll(r)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if !bytes.Equal(b, generate(1<<18)) {
|
|
t.Fatal("output does not match", len(b))
|
|
}
|
|
})
|
|
})
|
|
|
|
t.Run("zero reader", func(t *testing.T) {
|
|
t.Run("buffered reader", func(t *testing.T) {
|
|
r := buffer.BufferedReader(nil, buffer.Options{})
|
|
b, err := io.ReadAll(r)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if len(b) != 0 {
|
|
t.Fatal("output does not match", len(b))
|
|
}
|
|
})
|
|
|
|
t.Run("buffered content", func(t *testing.T) {
|
|
r := buffer.BufferedContent(nil, buffer.Options{})
|
|
b, err := io.ReadAll(r)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if len(b) != 0 {
|
|
t.Fatal("output does not match", len(b))
|
|
}
|
|
})
|
|
})
|
|
|
|
t.Run("uninitialized reader", func(t *testing.T) {
|
|
t.Run("read", func(t *testing.T) {
|
|
var r buffer.Reader
|
|
p := make([]byte, 512)
|
|
n, err := r.Read(p)
|
|
if !errors.Is(err, io.EOF) {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if n != 0 {
|
|
t.Fatal(n)
|
|
}
|
|
})
|
|
|
|
t.Run("read bytes", func(t *testing.T) {
|
|
var r buffer.Reader
|
|
b, ok, err := r.ReadBytes([]byte("123"), 512)
|
|
if !errors.Is(err, io.EOF) {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if ok {
|
|
t.Fatal(ok)
|
|
}
|
|
|
|
if len(b) != 0 {
|
|
t.Fatal(len(b))
|
|
}
|
|
})
|
|
|
|
t.Run("read utf8", func(t *testing.T) {
|
|
var r buffer.Reader
|
|
runes, n, err := r.ReadUTF8(512)
|
|
if !errors.Is(err, io.EOF) {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if n != 0 {
|
|
t.Fatal(n)
|
|
}
|
|
|
|
if len(runes) != 0 {
|
|
t.Fatal(len(runes))
|
|
}
|
|
})
|
|
|
|
t.Run("peek", func(t *testing.T) {
|
|
var r buffer.Reader
|
|
b, err := r.Peek(512)
|
|
if !errors.Is(err, io.EOF) {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if len(b) != 0 {
|
|
t.Fatal(len(b))
|
|
}
|
|
})
|
|
|
|
t.Run("buffered", func(t *testing.T) {
|
|
var r buffer.Reader
|
|
b := r.Buffered()
|
|
if len(b) != 0 {
|
|
t.Fatal(len(b))
|
|
}
|
|
})
|
|
|
|
t.Run("write to", func(t *testing.T) {
|
|
var (
|
|
r buffer.Reader
|
|
b bytes.Buffer
|
|
)
|
|
|
|
n, err := r.WriteTo(&b)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if n != 0 {
|
|
t.Fatal(n)
|
|
}
|
|
})
|
|
})
|
|
|
|
t.Run("abort", func(t *testing.T) {
|
|
t.Run("from blank state", func(t *testing.T) {
|
|
p := &fakePool{allocSize: 1 << 6}
|
|
r := buffer.BufferedReader(&gen{max: 1 << 12}, buffer.Options{Pool: p})
|
|
r.Close()
|
|
b := make([]byte, 1<<9)
|
|
n, err := r.Read(b)
|
|
if n != 0 || !errors.Is(err, buffer.ErrAbort) {
|
|
t.Fatal(n, err)
|
|
}
|
|
|
|
if p.alloc != 0 || p.free != 0 {
|
|
t.Fatal(p.alloc, p.free)
|
|
}
|
|
})
|
|
|
|
t.Run("with multiple segments", func(t *testing.T) {
|
|
p := &fakePool{allocSize: 1 << 6}
|
|
r := buffer.BufferedReader(&gen{max: 1 << 12}, buffer.Options{Pool: p})
|
|
b, ok, err := r.ReadBytes([]byte("123"), 1<<6+1<<5)
|
|
if ok || err != nil || p.alloc != 2 {
|
|
t.Fatal(len(b), ok, err, p.alloc)
|
|
}
|
|
|
|
r.Close()
|
|
b = make([]byte, 1<<9)
|
|
n, err := r.Read(b)
|
|
if n != 0 || !errors.Is(err, buffer.ErrAbort) {
|
|
t.Fatal(n, err)
|
|
}
|
|
|
|
if p.alloc != 2 || p.free != 2 {
|
|
t.Fatal(p.alloc, p.free)
|
|
}
|
|
})
|
|
|
|
t.Run("from err state", func(t *testing.T) {
|
|
p := &fakePool{allocSize: 1 << 6}
|
|
g := &gen{
|
|
max: 1 << 12,
|
|
errAfter: []int{1 << 6},
|
|
}
|
|
|
|
r := buffer.BufferedReader(g, buffer.Options{Pool: p})
|
|
b := make([]byte, 1<<9)
|
|
n, err := r.Read(b)
|
|
if n != 1<<6 || err != nil {
|
|
t.Fatal(n, err)
|
|
}
|
|
|
|
n, err = r.Read(b)
|
|
if n != 0 || !errors.Is(err, errTest) {
|
|
t.Fatal(n, err)
|
|
}
|
|
|
|
r.Close()
|
|
b = make([]byte, 1<<9)
|
|
n, err = r.Read(b)
|
|
if n != 0 || !errors.Is(err, errTest) {
|
|
t.Fatal(n, err)
|
|
}
|
|
|
|
if p.alloc != 1 || p.free != 1 {
|
|
t.Fatal(p.alloc, p.free)
|
|
}
|
|
})
|
|
|
|
t.Run("with content", func(t *testing.T) {
|
|
c := buffer.ContentFunc(func(w io.Writer) (int64, error) {
|
|
var n int64
|
|
for i := 0; i < 3; i++ {
|
|
ni, err := w.Write([]byte("123456789")[i*3 : i*3+3])
|
|
n += int64(ni)
|
|
if err != nil {
|
|
return n, err
|
|
}
|
|
}
|
|
|
|
return n, nil
|
|
})
|
|
|
|
p := &fakePool{allocSize: 2}
|
|
o := buffer.Options{Pool: p}
|
|
r := buffer.BufferedContent(c, o)
|
|
b := make([]byte, 3)
|
|
for i := 0; i < 2; i++ {
|
|
n, err := r.Read(b)
|
|
if n != 3 || err != nil {
|
|
t.Fatal(n, err)
|
|
}
|
|
|
|
if string(b) != "123456789"[i*3:i*3+3] {
|
|
t.Fatal(string(b))
|
|
}
|
|
}
|
|
|
|
r.Close()
|
|
n, err := r.Read(b)
|
|
if n != 0 || !errors.Is(err, buffer.ErrAbort) {
|
|
t.Fatal(n, err)
|
|
}
|
|
|
|
if p.alloc != 1 || p.free != 1 {
|
|
t.Fatal(p.alloc, p.free)
|
|
}
|
|
})
|
|
|
|
t.Run("with content error", func(t *testing.T) {
|
|
c := buffer.ContentFunc(func(w io.Writer) (int64, error) {
|
|
var n int64
|
|
for i := 0; i < 3; i++ {
|
|
ni, err := w.Write([]byte("123456789")[i*3 : i*3+3])
|
|
n += int64(ni)
|
|
if err != nil {
|
|
return n, err
|
|
}
|
|
}
|
|
|
|
return n, errTest
|
|
})
|
|
|
|
p := &fakePool{allocSize: 2}
|
|
o := buffer.Options{Pool: p}
|
|
r := buffer.BufferedContent(c, o)
|
|
b := make([]byte, 3)
|
|
for i := 0; i < 3; i++ {
|
|
n, err := r.Read(b)
|
|
if n != 3 || err != nil {
|
|
t.Fatal(n, err)
|
|
}
|
|
|
|
if string(b) != "123456789"[i*3:i*3+3] {
|
|
t.Fatal(string(b))
|
|
}
|
|
}
|
|
|
|
n, err := r.Read(b)
|
|
if n != 0 || !errors.Is(err, errTest) {
|
|
t.Fatal(n, err)
|
|
}
|
|
|
|
r.Close()
|
|
n, err = r.Read(b)
|
|
if n != 0 || !errors.Is(err, errTest) {
|
|
t.Fatal(n, err)
|
|
}
|
|
|
|
if p.alloc != 1 || p.free != 1 {
|
|
t.Fatal(p.alloc, p.free)
|
|
}
|
|
})
|
|
})
|
|
|
|
t.Run("writer", func(t *testing.T) {
|
|
t.Run("uninitialized writer", func(t *testing.T) {
|
|
t.Run("no writer", func(t *testing.T) {
|
|
w := buffer.BufferedWriter(nil, buffer.Options{})
|
|
if n, err := w.Write([]byte("123")); n != 0 || err == nil {
|
|
t.Fatal(n, err)
|
|
}
|
|
})
|
|
|
|
t.Run("write", func(t *testing.T) {
|
|
var w buffer.Writer
|
|
if n, err := w.Write([]byte("123")); n != 0 || err == nil {
|
|
t.Fatal(n, err)
|
|
}
|
|
})
|
|
|
|
t.Run("flush", func(t *testing.T) {
|
|
var w buffer.Writer
|
|
if err := w.Flush(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
})
|
|
|
|
t.Run("close", func(t *testing.T) {
|
|
var w buffer.Writer
|
|
if err := w.Close(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
})
|
|
})
|
|
|
|
t.Run("default pool", func(t *testing.T) {
|
|
w := &writer{}
|
|
b := buffer.BufferedWriter(w, buffer.Options{})
|
|
if n, err := b.Write([]byte("123")); n != 3 || err != nil {
|
|
t.Fatal(n, err)
|
|
}
|
|
|
|
if err := b.Close(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if string(w.written) != "123" {
|
|
t.Fatal(string(w.written))
|
|
}
|
|
})
|
|
})
|
|
}
|
|
|
|
// -- bench
|
|
|
|
type readerOnly struct {
|
|
in io.Reader
|
|
}
|
|
|
|
type writerOnly struct {
|
|
in io.Writer
|
|
}
|
|
|
|
func (r readerOnly) Read(p []byte) (int, error) {
|
|
return r.in.Read(p)
|
|
}
|
|
|
|
func (w writerOnly) Write(p []byte) (int, error) {
|
|
return w.in.Write(p)
|
|
}
|
|
|
|
func TestBenchmarkThroughput(t *testing.T) {
|
|
p := buffer.NoPool(0)
|
|
wo := writerOnly{io.Discard}
|
|
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 TestBenchmarkThroughputCompare(t *testing.T) {
|
|
wo := writerOnly{io.Discard}
|
|
src := &gen{max: 1 << 18}
|
|
r := bufio.NewReader(src)
|
|
ro := readerOnly{r}
|
|
n, err := io.Copy(wo, ro)
|
|
if n != 1<<18 || err != nil {
|
|
t.Fatal(n, err)
|
|
}
|
|
}
|
|
|
|
func BenchmarkThroughput(b *testing.B) {
|
|
p := buffer.NoPool(0)
|
|
wo := writerOnly{io.Discard}
|
|
for i := 0; i < b.N; i++ {
|
|
src := &gen{max: 1 << 18}
|
|
r := buffer.BufferedReader(src, buffer.Options{Pool: p})
|
|
ro := readerOnly{r}
|
|
io.Copy(wo, ro)
|
|
}
|
|
}
|
|
|
|
func BenchmarkThroughputCompare(b *testing.B) {
|
|
wo := writerOnly{io.Discard}
|
|
for i := 0; i < b.N; i++ {
|
|
src := &gen{max: 1 << 18}
|
|
r := bufio.NewReader(src)
|
|
ro := readerOnly{r}
|
|
io.Copy(wo, ro)
|
|
}
|
|
}
|
|
|
|
func TestBenchmarkThroughputPooled(t *testing.T) {
|
|
p := &foreverPool{allocSize: 1 << 12}
|
|
wo := writerOnly{io.Discard}
|
|
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 TestBenchmarkThroughputPooledCompare(t *testing.T) {
|
|
wo := writerOnly{io.Discard}
|
|
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}
|
|
wo := writerOnly{io.Discard}
|
|
for i := 0; i < b.N; i++ {
|
|
src := &gen{max: 1 << 18}
|
|
r := buffer.BufferedReader(src, buffer.Options{Pool: p})
|
|
ro := readerOnly{r}
|
|
io.Copy(wo, ro)
|
|
}
|
|
}
|
|
|
|
func BenchmarkThroughputPooledCompare(b *testing.B) {
|
|
wo := writerOnly{io.Discard}
|
|
r := bufio.NewReader(nil)
|
|
for i := 0; i < b.N; i++ {
|
|
src := &gen{max: 1 << 18}
|
|
r.Reset(src)
|
|
ro := readerOnly{r}
|
|
io.Copy(wo, ro)
|
|
}
|
|
}
|
|
|
|
func TestBenchmarkThroughputPooledParallel(t *testing.T) {
|
|
p := newSyncedForeverPool(func() []byte {
|
|
return make([]byte, 1<<12)
|
|
})
|
|
|
|
wo := writerOnly{io.Discard}
|
|
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 TestBenchmarkThroughputPooledParallelCompare(t *testing.T) {
|
|
p := newSyncedForeverPool(func() *bufio.Reader {
|
|
return bufio.NewReader(nil)
|
|
})
|
|
|
|
wo := writerOnly{io.Discard}
|
|
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.SetParallelism(128)
|
|
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}
|
|
wo := writerOnly{io.Discard}
|
|
io.Copy(wo, ro)
|
|
}
|
|
})
|
|
}
|
|
|
|
func BenchmarkThroughputPooledParallelCompare(b *testing.B) {
|
|
p := newSyncedForeverPool(func() *bufio.Reader {
|
|
return bufio.NewReader(nil)
|
|
})
|
|
|
|
b.ResetTimer()
|
|
b.SetParallelism(128)
|
|
b.RunParallel(func(pb *testing.PB) {
|
|
for pb.Next() {
|
|
r, _ := p.Get()
|
|
src := &gen{max: 1 << 18}
|
|
r.Reset(src)
|
|
ro := readerOnly{r}
|
|
wo := writerOnly{io.Discard}
|
|
io.Copy(wo, ro)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestBenchmarkScan(t *testing.T) {
|
|
const delimiterPosition = 1<<17 + 1<<16 - 3
|
|
p := buffer.NoPool(0)
|
|
src := &gen{
|
|
max: 1 << 18,
|
|
customContentAfter: []int{delimiterPosition},
|
|
customContent: map[int][]byte{delimiterPosition: []byte("123")},
|
|
}
|
|
|
|
r := buffer.BufferedReader(src, buffer.Options{Pool: p})
|
|
b, ok, err := r.ReadBytes([]byte{'1'}, 1<<18)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if !ok {
|
|
t.Fatal("delimiter")
|
|
}
|
|
|
|
if !bytes.Equal(b, append(generate(delimiterPosition), '1')) {
|
|
t.Fatal("content")
|
|
}
|
|
}
|
|
|
|
func TestBenchmarkScanCompare(t *testing.T) {
|
|
const delimiterPosition = 1<<17 + 1<<16 - 3
|
|
src := &gen{
|
|
max: 1 << 18,
|
|
customContentAfter: []int{delimiterPosition},
|
|
customContent: map[int][]byte{delimiterPosition: []byte("123")},
|
|
}
|
|
|
|
r := bufio.NewReader(src)
|
|
b, err := r.ReadBytes('1')
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if !bytes.Equal(b, append(generate(delimiterPosition), '1')) {
|
|
t.Fatal("content")
|
|
}
|
|
}
|
|
|
|
func BenchmarkScan(b *testing.B) {
|
|
const delimiterPosition = 1<<17 + 1<<16 - 3
|
|
p := buffer.NoPool(0)
|
|
for i := 0; i < b.N; i++ {
|
|
src := &gen{
|
|
max: 1 << 18,
|
|
customContentAfter: []int{delimiterPosition},
|
|
customContent: map[int][]byte{delimiterPosition: []byte("123")},
|
|
}
|
|
|
|
r := buffer.BufferedReader(src, buffer.Options{Pool: p})
|
|
r.ReadBytes([]byte{'1'}, 1<<18)
|
|
}
|
|
}
|
|
|
|
func BenchmarkScanCompare(b *testing.B) {
|
|
const delimiterPosition = 1<<17 + 1<<16 - 3
|
|
for i := 0; i < b.N; i++ {
|
|
src := &gen{
|
|
max: 1 << 18,
|
|
customContentAfter: []int{delimiterPosition},
|
|
customContent: map[int][]byte{delimiterPosition: []byte("123")},
|
|
}
|
|
|
|
r := bufio.NewReader(src)
|
|
r.ReadBytes('1')
|
|
}
|
|
}
|
|
|
|
func TestBenchmarkScanPooled(t *testing.T) {
|
|
const delimiterPosition = 1<<17 + 1<<16 - 3
|
|
p := &foreverPool{allocSize: 1 << 12}
|
|
src := &gen{
|
|
max: 1 << 18,
|
|
customContentAfter: []int{delimiterPosition},
|
|
customContent: map[int][]byte{delimiterPosition: []byte("123")},
|
|
}
|
|
|
|
r := buffer.BufferedReader(src, buffer.Options{Pool: p})
|
|
b, ok, err := r.ReadBytes([]byte{'1'}, 1<<18)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if !ok {
|
|
t.Fatal("delimiter")
|
|
}
|
|
|
|
if !bytes.Equal(b, append(generate(delimiterPosition), '1')) {
|
|
t.Fatal("content")
|
|
}
|
|
}
|
|
|
|
func TestBenchmarkScanPooledCompare(t *testing.T) {
|
|
const delimiterPosition = 1<<17 + 1<<16 - 3
|
|
src := &gen{
|
|
max: 1 << 18,
|
|
customContentAfter: []int{delimiterPosition},
|
|
customContent: map[int][]byte{delimiterPosition: []byte("123")},
|
|
}
|
|
|
|
r := bufio.NewReader(nil)
|
|
r.Reset(src)
|
|
b, err := r.ReadBytes('1')
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if !bytes.Equal(b, append(generate(delimiterPosition), '1')) {
|
|
t.Fatal("content")
|
|
}
|
|
}
|
|
|
|
func BenchmarkScanPooled(b *testing.B) {
|
|
const delimiterPosition = 1<<17 + 1<<16 - 3
|
|
p := &foreverPool{allocSize: 1 << 12}
|
|
for i := 0; i < b.N; i++ {
|
|
src := &gen{
|
|
max: 1 << 18,
|
|
customContentAfter: []int{delimiterPosition},
|
|
customContent: map[int][]byte{delimiterPosition: []byte("123")},
|
|
}
|
|
|
|
r := buffer.BufferedReader(src, buffer.Options{Pool: p})
|
|
r.ReadBytes([]byte{'1'}, 1<<18)
|
|
}
|
|
}
|
|
|
|
func BenchmarkScanPooledCompare(b *testing.B) {
|
|
const delimiterPosition = 1<<17 + 1<<16 - 3
|
|
r := bufio.NewReader(nil)
|
|
for i := 0; i < b.N; i++ {
|
|
src := &gen{
|
|
max: 1 << 18,
|
|
customContentAfter: []int{delimiterPosition},
|
|
customContent: map[int][]byte{delimiterPosition: []byte("123")},
|
|
}
|
|
|
|
r.Reset(src)
|
|
r.ReadBytes('1')
|
|
}
|
|
}
|
|
|
|
func TestBenchmarkScanPooledParallel(t *testing.T) {
|
|
const delimiterPosition = 1<<17 + 1<<16 - 3
|
|
p := newSyncedForeverPool(func() []byte {
|
|
return make([]byte, 1<<12)
|
|
})
|
|
|
|
src := &gen{
|
|
max: 1 << 18,
|
|
customContentAfter: []int{delimiterPosition},
|
|
customContent: map[int][]byte{delimiterPosition: []byte("123")},
|
|
}
|
|
|
|
r := buffer.BufferedReader(src, buffer.Options{Pool: p})
|
|
b, ok, err := r.ReadBytes([]byte{'1'}, 1<<18)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if !ok {
|
|
t.Fatal("delimiter")
|
|
}
|
|
|
|
if !bytes.Equal(b, append(generate(delimiterPosition), '1')) {
|
|
t.Fatal("content")
|
|
}
|
|
}
|
|
|
|
func TestBenchmarkScanPooledParallelCompare(t *testing.T) {
|
|
const delimiterPosition = 1<<17 + 1<<16 - 3
|
|
p := newSyncedForeverPool(func() *bufio.Reader {
|
|
return bufio.NewReader(nil)
|
|
})
|
|
|
|
src := &gen{
|
|
max: 1 << 18,
|
|
customContentAfter: []int{delimiterPosition},
|
|
customContent: map[int][]byte{delimiterPosition: []byte("123")},
|
|
}
|
|
|
|
r, err := p.Get()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
r.Reset(src)
|
|
b, err := r.ReadBytes('1')
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if !bytes.Equal(b, append(generate(delimiterPosition), '1')) {
|
|
t.Fatal("content")
|
|
}
|
|
}
|
|
|
|
func BenchmarkScanPooledParallel(b *testing.B) {
|
|
const delimiterPosition = 1<<17 + 1<<16 - 3
|
|
p := newSyncedForeverPool(func() []byte {
|
|
return make([]byte, 1<<12)
|
|
})
|
|
|
|
b.ResetTimer()
|
|
b.SetParallelism(128)
|
|
b.RunParallel(func(pb *testing.PB) {
|
|
for pb.Next() {
|
|
src := &gen{
|
|
max: 1 << 18,
|
|
customContentAfter: []int{delimiterPosition},
|
|
customContent: map[int][]byte{delimiterPosition: []byte("123")},
|
|
}
|
|
|
|
r := buffer.BufferedReader(src, buffer.Options{Pool: p})
|
|
r.ReadBytes([]byte{'1'}, 1<<18)
|
|
}
|
|
})
|
|
}
|
|
|
|
func BenchmarkScanPooledParallelCompare(b *testing.B) {
|
|
const delimiterPosition = 1<<17 + 1<<16 - 3
|
|
p := newSyncedForeverPool(func() *bufio.Reader {
|
|
return bufio.NewReader(nil)
|
|
})
|
|
|
|
b.ResetTimer()
|
|
b.SetParallelism(128)
|
|
b.RunParallel(func(pb *testing.PB) {
|
|
for pb.Next() {
|
|
src := &gen{
|
|
max: 1 << 18,
|
|
customContentAfter: []int{delimiterPosition},
|
|
customContent: map[int][]byte{delimiterPosition: []byte("123")},
|
|
}
|
|
|
|
r, _ := p.Get()
|
|
r.Reset(src)
|
|
r.ReadBytes('1')
|
|
}
|
|
})
|
|
}
|