github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/grpc/encoding/proto/proto_benchmark_test.go (about)

     1  /*
     2   *
     3   * Copyright 2014 gRPC authors.
     4   *
     5   * Licensed under the Apache License, Version 2.0 (the "License");
     6   * you may not use this file except in compliance with the License.
     7   * You may obtain a copy of the License at
     8   *
     9   *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   *
    17   */
    18  
    19  package proto
    20  
    21  import (
    22  	"fmt"
    23  	"testing"
    24  
    25  	"github.com/golang/protobuf/proto"
    26  	"github.com/hxx258456/ccgo/grpc/encoding"
    27  	"github.com/hxx258456/ccgo/grpc/test/codec_perf"
    28  )
    29  
    30  func setupBenchmarkProtoCodecInputs(payloadBaseSize uint32) []proto.Message {
    31  	payloadBase := make([]byte, payloadBaseSize)
    32  	// arbitrary byte slices
    33  	payloadSuffixes := [][]byte{
    34  		[]byte("one"),
    35  		[]byte("two"),
    36  		[]byte("three"),
    37  		[]byte("four"),
    38  		[]byte("five"),
    39  	}
    40  	protoStructs := make([]proto.Message, 0)
    41  
    42  	for _, p := range payloadSuffixes {
    43  		ps := &codec_perf.Buffer{}
    44  		ps.Body = append(payloadBase, p...)
    45  		protoStructs = append(protoStructs, ps)
    46  	}
    47  
    48  	return protoStructs
    49  }
    50  
    51  // The possible use of certain protobuf APIs like the proto.Buffer API potentially involves caching
    52  // on our side. This can add checks around memory allocations and possible contention.
    53  // Example run: go test -v -run=^$ -bench=BenchmarkProtoCodec -benchmem
    54  func BenchmarkProtoCodec(b *testing.B) {
    55  	// range of message sizes
    56  	payloadBaseSizes := make([]uint32, 0)
    57  	for i := uint32(0); i <= 12; i += 4 {
    58  		payloadBaseSizes = append(payloadBaseSizes, 1<<i)
    59  	}
    60  	// range of SetParallelism
    61  	parallelisms := make([]int, 0)
    62  	for i := uint32(0); i <= 16; i += 4 {
    63  		parallelisms = append(parallelisms, int(1<<i))
    64  	}
    65  	for _, s := range payloadBaseSizes {
    66  		for _, p := range parallelisms {
    67  			protoStructs := setupBenchmarkProtoCodecInputs(s)
    68  			name := fmt.Sprintf("MinPayloadSize:%v/SetParallelism(%v)", s, p)
    69  			b.Run(name, func(b *testing.B) {
    70  				codec := &codec{}
    71  				b.SetParallelism(p)
    72  				b.RunParallel(func(pb *testing.PB) {
    73  					benchmarkProtoCodec(codec, protoStructs, pb, b)
    74  				})
    75  			})
    76  		}
    77  	}
    78  }
    79  
    80  func benchmarkProtoCodec(codec *codec, protoStructs []proto.Message, pb *testing.PB, b *testing.B) {
    81  	counter := 0
    82  	for pb.Next() {
    83  		counter++
    84  		ps := protoStructs[counter%len(protoStructs)]
    85  		fastMarshalAndUnmarshal(codec, ps, b)
    86  	}
    87  }
    88  
    89  func fastMarshalAndUnmarshal(codec encoding.Codec, protoStruct proto.Message, b *testing.B) {
    90  	marshaledBytes, err := codec.Marshal(protoStruct)
    91  	if err != nil {
    92  		b.Errorf("codec.Marshal(_) returned an error")
    93  	}
    94  	res := codec_perf.Buffer{}
    95  	if err := codec.Unmarshal(marshaledBytes, &res); err != nil {
    96  		b.Errorf("codec.Unmarshal(_) returned an error")
    97  	}
    98  }