From 93534fe94a1df9bd5a804b30c926b71c477974d9 Mon Sep 17 00:00:00 2001 From: wdvxdr Date: Fri, 12 Mar 2021 15:55:50 +0800 Subject: [PATCH] improve binary.Writer --- binary/writer.go | 45 ++++++++++---- binary/writer_test.go | 140 ++++++++++++++++++++++++++++++++++++++++++ go.mod | 2 +- go.sum | 7 +-- 4 files changed, 177 insertions(+), 17 deletions(-) create mode 100644 binary/writer_test.go diff --git a/binary/writer.go b/binary/writer.go index 103eeb4e..c10bae28 100644 --- a/binary/writer.go +++ b/binary/writer.go @@ -5,26 +5,51 @@ import ( "encoding/binary" ) -type Writer struct { - buf *bytes.Buffer +type Writer bytes.Buffer + +/* +var bufferPool = sync.Pool{ // todo sync.Pool 无法通过单元测试 + New: func() interface{} { + return new(bytes.Buffer) + }, } +func NewBuffer() *bytes.Buffer { + return bufferPool.Get().(*bytes.Buffer) +} + +func PutBuffer(buf *bytes.Buffer) { + // See https://golang.org/issue/23199 + const maxSize = 1 << 16 + if buf.Cap() < maxSize { // 对于大Buffer直接丢弃 + buf.Reset() + bufferPool.Put(buf) + } +} +*/ + func NewWriter() *Writer { - return &Writer{buf: new(bytes.Buffer)} + return new(Writer) } +/* +func PutWriter(w *Writer) { + PutBuffer((*bytes.Buffer)(w)) +} +*/ + func NewWriterF(f func(writer *Writer)) []byte { - w := NewWriter() - f(w) + w := new(bytes.Buffer) + f((*Writer)(w)) return w.Bytes() } func (w *Writer) Write(b []byte) { - w.buf.Write(b) + (*bytes.Buffer)(w).Write(b) } func (w *Writer) WriteByte(b byte) { - w.buf.WriteByte(b) + (*bytes.Buffer)(w).WriteByte(b) } func (w *Writer) WriteUInt16(v uint16) { @@ -70,9 +95,7 @@ func (w *Writer) EncryptAndWrite(key []byte, data []byte) { } func (w *Writer) WriteIntLvPacket(offset int, f func(writer *Writer)) { - t := NewWriter() - f(t) - data := t.Bytes() + data := NewWriterF(f) w.WriteUInt32(uint32(len(data) + offset)) w.Write(data) } @@ -108,5 +131,5 @@ func (w *Writer) WriteTlvLimitedSize(data []byte, limit int) { } func (w *Writer) Bytes() []byte { - return w.buf.Bytes() + return (*bytes.Buffer)(w).Bytes() } diff --git a/binary/writer_test.go b/binary/writer_test.go new file mode 100644 index 00000000..a62fb674 --- /dev/null +++ b/binary/writer_test.go @@ -0,0 +1,140 @@ +package binary + +import ( + "bytes" + "encoding/hex" + "fmt" + "math/rand" + "sync" + "testing" +) + +func NewWriterFOld(f func(writer *Writer)) []byte { + w := (*Writer)(new(bytes.Buffer)) + f(w) + return w.Bytes() +} + +func TestNewWriterF(t *testing.T) { + wg := sync.WaitGroup{} + for i := 0; i < 10000; i++ { + wg.Add(1) + go func() { + defer wg.Done() + test := make([]byte, 1024) + rand.Read(test) + b1 := NewWriterFOld(func(writer *Writer) { + writer.Write(test) + writer.Write(NewWriterFOld(func(writer *Writer) { + writer.Write(test) + writer.Write(NewWriterFOld(func(writer *Writer) { + writer.Write(test) + })) + })) + }) + + b2 := NewWriterF(func(writer *Writer) { + writer.Write(test) + writer.Write(NewWriterF(func(writer *Writer) { + writer.Write(test) + writer.Write(NewWriterF(func(writer *Writer) { + writer.Write(test) + })) + })) + }) + + if !bytes.Equal(b1, b2) { + fmt.Println(hex.EncodeToString(b1)) + fmt.Println(hex.EncodeToString(b2)) + t.Error("Not equal!!!") + } + }() + } + wg.Wait() +} + +func BenchmarkNewWriterFOld256(b *testing.B) { + test := make([]byte, 256) + rand.Read(test) + b.StartTimer() + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + NewWriterFOld(func(w *Writer) { + w.Write(test) + }) + } + }) +} + +func BenchmarkNewWriterF256(b *testing.B) { + test := make([]byte, 256) + rand.Read(test) + b.StartTimer() + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + NewWriterF(func(w *Writer) { + w.Write(test) + }) + } + }) +} + +func BenchmarkNewWriterFOld1024(b *testing.B) { + test := make([]byte, 1024) + rand.Read(test) + b.StartTimer() + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + NewWriterFOld(func(w *Writer) { + w.Write(test) + }) + } + }) +} + +func BenchmarkNewWriterF1024(b *testing.B) { + test := make([]byte, 1024) + rand.Read(test) + b.StartTimer() + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + NewWriterF(func(w *Writer) { + w.Write(test) + }) + } + }) +} + +func BenchmarkNewWriterFOld128_5(b *testing.B) { + test := make([]byte, 128) + rand.Read(test) + b.StartTimer() + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + NewWriterFOld(func(w *Writer) { + w.Write(test) + w.Write(test) + w.Write(test) + w.Write(test) + w.Write(test) + }) + } + }) +} + +func BenchmarkNewWriterF128_5(b *testing.B) { + test := make([]byte, 128) + rand.Read(test) + b.StartTimer() + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + NewWriterF(func(w *Writer) { + w.Write(test) + w.Write(test) + w.Write(test) + w.Write(test) + w.Write(test) + }) + } + }) +} diff --git a/go.mod b/go.mod index 41ee143e..dab1e4a4 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.15 require ( github.com/golang/protobuf v1.4.3 github.com/json-iterator/go v1.1.10 - github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 + github.com/modern-go/reflect2 v1.0.1 github.com/pkg/errors v0.9.1 google.golang.org/protobuf v1.25.0 ) diff --git a/go.sum b/go.sum index 99881c34..c618df25 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,5 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/a8m/syncmap v0.0.0-20200818084611-4bbbd178de97 h1:QJIAdw5m5tNUy7fjBxgg73+YUs/AkeESeqdJ1L3lN10= -github.com/a8m/syncmap v0.0.0-20200818084611-4bbbd178de97/go.mod h1:f3iF7/3t9i9hsYF8DPgT0XeIVyNzevhMCKf2445Q6pE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -32,8 +30,9 @@ github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -61,8 +60,6 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190501045030-23463209683d/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135 h1:5Beo0mZN8dRzgrMMkDp0jc8YXQKx9DiJ2k1dkvGsn5A= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=