Skip to content

Commit 833ed64

Browse files
authored
flatbuffers: add unsafe_reuse benchmarks (#178)
* flatbuffers: Add unsafe_reuse benchmark * Update report
1 parent 5753fe8 commit 833ed64

File tree

3 files changed

+372
-321
lines changed

3 files changed

+372
-321
lines changed

benchmarks.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,15 @@ var benchmarkCases = []BenchmarkCase{
226226

227227
TimeSupport: TSNoSupport,
228228
APIKind: AKCodegen,
229+
}, {
230+
Name: "flatbuffers/unsafe_reuse",
231+
URL: "github.com/google/flatbuffers/go",
232+
New: flatbuffers.NewFlatBuffersUnsafeReuseSerializer,
233+
234+
TimeSupport: TSNoSupport,
235+
APIKind: AKCodegen,
236+
UnsafeStringUnmarshal: true,
237+
BufferReuseMarshal: true,
229238
}, {
230239
Name: "capnproto",
231240
URL: "github.com/glycerine/go-capnproto",

internal/serializers/flatbuffers/flatbuffers.go

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,23 @@ package flatbuffers
22

33
import (
44
"time"
5+
"unsafe"
56

67
"github.com/alecthomas/go_serialization_benchmarks/goserbench"
78
flatbuffers "github.com/google/flatbuffers/go"
89
)
910

1011
type FlatBufferSerializer struct {
11-
builder *flatbuffers.Builder
12+
unsafeReuse bool
13+
builder *flatbuffers.Builder
1214
}
1315

1416
func (s *FlatBufferSerializer) Marshal(o interface{}) ([]byte, error) {
1517
a := o.(*goserbench.SmallStruct)
1618
builder := s.builder
17-
builder.Bytes = nil // free
19+
if !s.unsafeReuse {
20+
builder.Bytes = nil // free
21+
}
1822
builder.Reset()
1923

2024
name := builder.CreateString(a.Name)
@@ -28,22 +32,38 @@ func (s *FlatBufferSerializer) Marshal(o interface{}) ([]byte, error) {
2832
FlatBufferAAddSpouse(builder, a.Spouse)
2933
FlatBufferAAddMoney(builder, a.Money)
3034
builder.Finish(FlatBufferAEnd(builder))
31-
return builder.Bytes[builder.Head():], nil
35+
return builder.FinishedBytes(), nil
3236
}
3337

3438
func (s *FlatBufferSerializer) Unmarshal(d []byte, i interface{}) error {
3539
a := i.(*goserbench.SmallStruct)
3640
o := FlatBufferA{}
3741
o.Init(d, flatbuffers.GetUOffsetT(d))
38-
a.Name = string(o.Name())
42+
if s.unsafeReuse {
43+
a.Name = unsafeSliceToString(o.Name())
44+
a.Phone = unsafeSliceToString(o.Phone())
45+
} else {
46+
a.Name = string(o.Name())
47+
a.Phone = string(o.Phone())
48+
}
3949
a.BirthDay = time.Unix(0, o.BirthDay())
40-
a.Phone = string(o.Phone())
4150
a.Siblings = int(o.Siblings())
4251
a.Spouse = o.Spouse()
4352
a.Money = o.Money()
4453
return nil
4554
}
4655

4756
func NewFlatBuffersSerializer() goserbench.Serializer {
48-
return &FlatBufferSerializer{flatbuffers.NewBuilder(0)}
57+
return &FlatBufferSerializer{builder: flatbuffers.NewBuilder(0), unsafeReuse: false}
58+
}
59+
60+
func NewFlatBuffersUnsafeReuseSerializer() goserbench.Serializer {
61+
const maxSerSize = 128
62+
return &FlatBufferSerializer{builder: flatbuffers.NewBuilder(maxSerSize), unsafeReuse: true}
63+
}
64+
65+
// unsafeSliceToString converts a byte slice to a string in an unsafe way
66+
// (modifications to the byte slice modify the string).
67+
func unsafeSliceToString(b []byte) string {
68+
return *(*string)(unsafe.Pointer(&b))
4969
}

0 commit comments

Comments
 (0)