func BenchmarkProtoCodec(b *testing.B) {
	payloadBaseSizes := make([]uint32, 0)
	for i := uint32(0); i <= 12; i += 4 {
		payloadBaseSizes = append(payloadBaseSizes, 1<<i)
	}
	parallelisms := make([]int, 0)
	for i := uint32(0); i <= 16; i += 4 {
		parallelisms = append(parallelisms, int(1<<i))
	}
	for _, s := range payloadBaseSizes {
		for _, p := range parallelisms {
			protoStructs := setupBenchmarkProtoCodecInputs(s)
			name := fmt.Sprintf("MinPayloadSize:%v/SetParallelism(%v)", s, p)
			b.Run(name, func(b *testing.B) {
				codec := &codec{}
				b.SetParallelism(p)
				b.RunParallel(func(pb *testing.PB) {
					benchmarkProtoCodec(codec, protoStructs, pb, b)
				})
			})
		}
	}
}
The possible use of certain protobuf APIs like the proto.Buffer API potentially involves caching
on our side. This can add checks around memory allocations and possible contention.
Example run: go test -v -run=^$ -bench=BenchmarkProtoCodec -benchmem
package proto
import (
	"fmt"
	"testing"
	"github.com/golang/protobuf/proto"
	"google.golang.org/grpc/encoding"
	"google.golang.org/grpc/test/codec_perf"
)
func setupBenchmarkProtoCodecInputs(payloadBaseSize uint32) []proto.Message {
	payloadBase := make([]byte, payloadBaseSize)
	payloadSuffixes := [][]byte{
		[]byte("one"),
		[]byte("two"),
		[]byte("three"),
		[]byte("four"),
		[]byte("five"),
	}
	protoStructs := make([]proto.Message, 0)
	for _, p := range payloadSuffixes {
		ps := &codec_perf.Buffer{}
		ps.Body = append(payloadBase, p...)
		protoStructs = append(protoStructs, ps)
	}
	return protoStructs
}