~bigbes/tarantool

tarantool-protobuf

ref: 53840866a6ef3349d42bf589a6646aaad6869386 tarantool-protobuf/bench/go/bench_test.go -rw-r--r-- 3.5 KiB
53840866 — Eugene Blikh codegen: emit <Msg>_decode_unsafe for trusted-source decoding (6bb) 2 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)
				}
			}
		})
	}
}