github.com/sandwich-go/boost@v1.3.29/xencoding/protobuf/codec_benchmark_test.go (about)

     1  package protobuf
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"github.com/sandwich-go/boost/xencoding"
     7  	"github.com/sandwich-go/boost/xencoding/protobuf/test_perf"
     8  	"testing"
     9  
    10  	"github.com/golang/protobuf/proto"
    11  )
    12  
    13  func setupBenchmarkProtoCodecInputs(payloadBaseSize uint32) []proto.Message {
    14  	payloadBase := make([]byte, payloadBaseSize)
    15  	// arbitrary byte slices
    16  	payloadSuffixes := [][]byte{
    17  		[]byte("one"),
    18  		[]byte("two"),
    19  		[]byte("three"),
    20  		[]byte("four"),
    21  		[]byte("five"),
    22  	}
    23  	protoStructs := make([]proto.Message, 0)
    24  
    25  	for _, p := range payloadSuffixes {
    26  		ps := &test_perf.Buffer{}
    27  		ps.Body = append(payloadBase, p...)
    28  		protoStructs = append(protoStructs, ps)
    29  	}
    30  
    31  	return protoStructs
    32  }
    33  
    34  // The possible use of certain protobuf APIs like the proto.Buffer API potentially involves caching
    35  // on our side. This can add checks around memory allocations and possible contention.
    36  // Example run: go test -v -run=^$ -bench=BenchmarkProtoCodec -benchmem
    37  func BenchmarkProtoCodec(b *testing.B) {
    38  	// range of message sizes
    39  	payloadBaseSizes := make([]uint32, 0)
    40  	for i := uint32(0); i <= 12; i += 4 {
    41  		payloadBaseSizes = append(payloadBaseSizes, 1<<i)
    42  	}
    43  	// range of SetParallelism
    44  	parallelisms := make([]int, 0)
    45  	for i := uint32(0); i <= 16; i += 4 {
    46  		parallelisms = append(parallelisms, int(1<<i))
    47  	}
    48  	for _, s := range payloadBaseSizes {
    49  		for _, p := range parallelisms {
    50  			protoStructs := setupBenchmarkProtoCodecInputs(s)
    51  			name := fmt.Sprintf("MinPayloadSize:%v/SetParallelism(%v)", s, p)
    52  			b.Run(name, func(b *testing.B) {
    53  				codec := &codec{}
    54  				b.SetParallelism(p)
    55  				b.RunParallel(func(pb *testing.PB) {
    56  					benchmarkProtoCodec(codec, protoStructs, pb, b)
    57  				})
    58  			})
    59  		}
    60  	}
    61  }
    62  
    63  func benchmarkProtoCodec(codec *codec, protoStructs []proto.Message, pb *testing.PB, b *testing.B) {
    64  	counter := 0
    65  	for pb.Next() {
    66  		counter++
    67  		ps := protoStructs[counter%len(protoStructs)]
    68  		fastMarshalAndUnmarshal(codec, ps, b)
    69  	}
    70  }
    71  
    72  func fastMarshalAndUnmarshal(codec xencoding.Codec, protoStruct proto.Message, b *testing.B) {
    73  	marshaledBytes, err := codec.Marshal(context.Background(), protoStruct)
    74  	if err != nil {
    75  		b.Errorf("codec.Marshal(_) returned an error")
    76  	}
    77  	res := test_perf.Buffer{}
    78  	if err := codec.Unmarshal(context.Background(), marshaledBytes, &res); err != nil {
    79  		b.Errorf("codec.Unmarshal(_) returned an error")
    80  	}
    81  }