~bigbes/tarantool

tarantool-protobuf

ref: c85386b1692ea4af5ad52aa383a49576f7f50d2e tarantool-protobuf/bench/go/bench_test.go -rw-r--r-- 3.5 KiB
c85386b1 — Eugene Blikh bench: record gcy (inline nested-message decode) post-mortem 3 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// Standard `go test -bench=.` benchmarks. Mirrors bench/bench.lua: per
// fixture × per size, encode + decode, throughput + alloc.
//
// Two implementations per case:
//   * apiv2:   google.golang.org/protobuf reflective Marshal/Unmarshal
//              — the default everyone gets out of the box.
//   * vtproto: planetscale/vtprotobuf generated MarshalVT/UnmarshalVT
//              — the fastest pure-Go path, conceptually equivalent to
//              our `mode=full` codegen.
//
// Runs are single-threaded by default (testing.B doesn't parallelize
// unless RunParallel is called).
package bench

import (
	"fmt"
	"testing"

	"google.golang.org/protobuf/proto"

	hellopb "github.com/tarantool-protobuf/bench/go/pb/hellopb"
	proto2pb "github.com/tarantool-protobuf/bench/go/pb/proto2pb"
)

// --- hello.Person ---------------------------------------------------------

func BenchmarkPersonEncode(b *testing.B) {
	for _, sz := range PersonSizes {
		msg := BuildPerson(sz.Target)
		wire, err := proto.Marshal(msg)
		if err != nil {
			b.Fatal(err)
		}

		b.Run(fmt.Sprintf("apiv2/%s", sz.Label), func(b *testing.B) {
			b.SetBytes(int64(len(wire)))
			b.ReportAllocs()
			for i := 0; i < b.N; i++ {
				if _, err := proto.Marshal(msg); err != nil {
					b.Fatal(err)
				}
			}
		})

		b.Run(fmt.Sprintf("vtproto/%s", sz.Label), func(b *testing.B) {
			b.SetBytes(int64(len(wire)))
			b.ReportAllocs()
			for i := 0; i < b.N; i++ {
				if _, err := msg.MarshalVT(); err != nil {
					b.Fatal(err)
				}
			}
		})
	}
}

func BenchmarkPersonDecode(b *testing.B) {
	for _, sz := range PersonSizes {
		msg := BuildPerson(sz.Target)
		wire, err := proto.Marshal(msg)
		if err != nil {
			b.Fatal(err)
		}

		b.Run(fmt.Sprintf("apiv2/%s", sz.Label), func(b *testing.B) {
			b.SetBytes(int64(len(wire)))
			b.ReportAllocs()
			for i := 0; i < b.N; i++ {
				var out hellopb.Person
				if err := proto.Unmarshal(wire, &out); err != nil {
					b.Fatal(err)
				}
			}
		})

		b.Run(fmt.Sprintf("vtproto/%s", sz.Label), func(b *testing.B) {
			b.SetBytes(int64(len(wire)))
			b.ReportAllocs()
			for i := 0; i < b.N; i++ {
				var out hellopb.Person
				if err := out.UnmarshalVT(wire); err != nil {
					b.Fatal(err)
				}
			}
		})
	}
}

// --- proto2_basic.BenchPayload --------------------------------------------

func BenchmarkProto2Encode(b *testing.B) {
	for _, sz := range Proto2Sizes {
		msg := BuildProto2(sz.Target)
		wire, err := proto.Marshal(msg)
		if err != nil {
			b.Fatal(err)
		}

		b.Run(fmt.Sprintf("apiv2/%s", sz.Label), func(b *testing.B) {
			b.SetBytes(int64(len(wire)))
			b.ReportAllocs()
			for i := 0; i < b.N; i++ {
				if _, err := proto.Marshal(msg); err != nil {
					b.Fatal(err)
				}
			}
		})

		// vtproto's generated MarshalVT does not serialize extensions —
		// it skips XXX_unrecognized + protoimpl.ExtensionFields and so
		// drops the ext_count/ext_label payload. The benchmark would
		// produce shorter bytes than apiv2; skip the vtproto variant
		// when the fixture carries extensions so we don't publish
		// misleading throughput numbers.
		_ = msg.MarshalVT // keep symbol referenced; intentionally not benched
	}
}

func BenchmarkProto2Decode(b *testing.B) {
	for _, sz := range Proto2Sizes {
		msg := BuildProto2(sz.Target)
		wire, err := proto.Marshal(msg)
		if err != nil {
			b.Fatal(err)
		}

		b.Run(fmt.Sprintf("apiv2/%s", sz.Label), func(b *testing.B) {
			b.SetBytes(int64(len(wire)))
			b.ReportAllocs()
			for i := 0; i < b.N; i++ {
				var out proto2pb.BenchPayload
				if err := proto.Unmarshal(wire, &out); err != nil {
					b.Fatal(err)
				}
			}
		})
	}
}