mirror of
https://github.com/protocolbuffers/protobuf-go.git
synced 2024-12-27 06:21:25 +00:00
eb7b468655
For golang/protobuf#1657 Change-Id: I7b2b0c30506706015ce278e6054439c9ad9ef727 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/634815 TryBot-Bypass: Michael Stapelberg <stapelberg@google.com> Reviewed-by: Joseph Tsai <joetsai@digital-static.net> Reviewed-by: Damien Neil <dneil@google.com>
93 lines
2.7 KiB
Go
93 lines
2.7 KiB
Go
// Copyright 2024 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package proto_test
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"google.golang.org/protobuf/proto"
|
|
|
|
lazyopaquepb "google.golang.org/protobuf/internal/testprotos/lazy/lazy_opaque"
|
|
)
|
|
|
|
// testMessageLinked returns a test message with a few fields of various
|
|
// possible types filled in that nests more messages like a linked list.
|
|
func testMessageLinked(nesting int) *lazyopaquepb.Node {
|
|
const (
|
|
shortVarint = 23 // encodes into 1 byte
|
|
longVarint = 562949953421312 // encodes into 8 bytes
|
|
)
|
|
msg := lazyopaquepb.Node_builder{
|
|
Int32: proto.Int32(shortVarint),
|
|
Int64: proto.Int64(longVarint),
|
|
Uint32: proto.Uint32(shortVarint),
|
|
Uint64: proto.Uint64(longVarint),
|
|
Sint32: proto.Int32(shortVarint),
|
|
Sint64: proto.Int64(longVarint),
|
|
Fixed32: proto.Uint32(shortVarint),
|
|
Fixed64: proto.Uint64(longVarint),
|
|
Sfixed32: proto.Int32(shortVarint),
|
|
Sfixed64: proto.Int64(longVarint),
|
|
Float: proto.Float32(23.42),
|
|
Double: proto.Float64(23.42),
|
|
Bool: proto.Bool(true),
|
|
String: proto.String("hello"),
|
|
Bytes: []byte("world"),
|
|
}.Build()
|
|
if nesting > 0 {
|
|
msg.SetNested(testMessageLinked(nesting - 1))
|
|
}
|
|
return msg
|
|
}
|
|
|
|
// A higher nesting level than 15 messages deep does not result in (relative)
|
|
// performance changes. In other words, the full effect of lazy decoding is
|
|
// visible with a nesting level of 15 messages deep. Lower nesting levels (like
|
|
// 5 messages deep) also show significant improvement.
|
|
const nesting = 15
|
|
|
|
func BenchmarkUnmarshal(b *testing.B) {
|
|
encoded, err := proto.Marshal(testMessageLinked(nesting))
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
|
|
for _, tt := range []struct {
|
|
desc string
|
|
uopts proto.UnmarshalOptions
|
|
}{
|
|
{
|
|
desc: "lazy",
|
|
uopts: proto.UnmarshalOptions{},
|
|
},
|
|
|
|
// When running the benchmark directly, print lazy vs. nolazy in the
|
|
// same run. When using the benchstat tool, you can compare lazy
|
|
// vs. nolazy by running only the lazy variant and disabling lazy
|
|
// decoding with the -test_lazy_unmarshal command-line flag:
|
|
//
|
|
// benchstat \
|
|
// nolazy=<(go test -run=^$ -bench=Unmarshal/^lazy -count=6) \
|
|
// lazy=<(go test -run=^$ -bench=Unmarshal/^lazy -count=6 -test_lazy_unmarshal)
|
|
{
|
|
desc: "nolazy",
|
|
uopts: proto.UnmarshalOptions{
|
|
NoLazyDecoding: true,
|
|
},
|
|
},
|
|
} {
|
|
b.Run(tt.desc, func(b *testing.B) {
|
|
b.ResetTimer()
|
|
b.ReportAllocs()
|
|
for i := 0; i < b.N; i++ {
|
|
out := &lazyopaquepb.Node{}
|
|
if err := tt.uopts.Unmarshal(encoded, out); err != nil {
|
|
b.Fatalf("can't unmarshal message: %v", err)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|