Skip to content

Commit

Permalink
perf(thrift): WriteStringNocopy one less func call (#32)
Browse files Browse the repository at this point in the history
goos: darwin
goarch: arm64
pkg: github.com/cloudwego/gopkg/protocol/thrift
                                 │  ./old.txt  │             ./new.txt              │
                                 │   sec/op    │   sec/op     vs base               │
WriteString/WriteStringNoCopy-12   4.336n ± 1%   2.374n ± 0%  -45.25% (p=0.002 n=6)
  • Loading branch information
xiaost authored Nov 15, 2024
1 parent e702cb5 commit a218fe6
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 3 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,8 @@ output/*
# Go workspace file
go.work
go.work.sum


# benchmark comparision
old.txt
new.txt
7 changes: 6 additions & 1 deletion protocol/thrift/binary.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,12 @@ func (BinaryProtocol) WriteString(buf []byte, v string) int {
}

func (p BinaryProtocol) WriteStringNocopy(buf []byte, w NocopyWriter, v string) int {
return p.WriteBinaryNocopy(buf, w, hack.StringToByteSlice(v))
if w == nil || len(v) < nocopyWriteThreshold {
return p.WriteString(buf, v)
}
binary.BigEndian.PutUint32(buf, uint32(len(v)))
_ = w.WriteDirect(hack.StringToByteSlice(v), len(buf[4:])) // always err == nil ?
return 4
}

// Append methods
Expand Down
23 changes: 21 additions & 2 deletions protocol/thrift/binary_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,7 @@ func TestNocopyWrite(t *testing.T) {
expectb := make([]byte, 0, 2*x.StringLength(smallstr)+x.StringLength(largestr))
expectb = x.AppendString(expectb, smallstr)
expectb = x.AppendString(expectb, largestr)
expectb = x.AppendString(expectb, largestr)
expectb = x.AppendString(expectb, smallstr)

// generate testing data
Expand All @@ -436,8 +437,26 @@ func TestNocopyWrite(t *testing.T) {
b := w.Malloc(len(expectb))
i += x.WriteStringNocopy(b[i:], w, smallstr)
i += x.WriteStringNocopy(b[i:], w, largestr)
i += x.WriteBinaryNocopy(b[i:], w, []byte(largestr))
i += x.WriteStringNocopy(b[i:], w, smallstr)
require.Equal(t, len(expectb)-len(largestr), i) // without len(largestr)
require.Equal(t, 1, w.WriteDirectN())
require.Equal(t, len(expectb)-i, 2*len(largestr)) // without 2*len(largestr)
require.Equal(t, 2, w.WriteDirectN())
require.Equal(t, expectb, w.Bytes())
}

func BenchmarkWriteString(b *testing.B) {
smallstr := "helloworld"
buf := make([]byte, 4+len(smallstr))
x := BinaryProtocol{}

b.Run("WriteString", func(b *testing.B) {
for i := 0; i < b.N; i++ {
x.WriteString(buf, smallstr)
}
})
b.Run("WriteStringNoCopy", func(b *testing.B) {
for i := 0; i < b.N; i++ {
x.WriteStringNocopy(buf, nil, smallstr)
}
})
}

0 comments on commit a218fe6

Please sign in to comment.