github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/tm2/pkg/amino/benchmark_test.go (about)

     1  package amino_test
     2  
     3  import (
     4  	"math/rand"
     5  	"reflect"
     6  	"runtime/debug"
     7  	"testing"
     8  
     9  	fuzz "github.com/google/gofuzz"
    10  	"github.com/stretchr/testify/require"
    11  	"google.golang.org/protobuf/proto"
    12  
    13  	"github.com/gnolang/gno/tm2/pkg/amino"
    14  	"github.com/gnolang/gno/tm2/pkg/amino/tests"
    15  )
    16  
    17  func BenchmarkBinary(b *testing.B) {
    18  	if testing.Short() {
    19  		b.Skip("skipping testing in short mode")
    20  	}
    21  
    22  	cdc := amino.NewCodec()
    23  	for _, ptr := range tests.StructTypes {
    24  		b.Logf("case %v", reflect.TypeOf(ptr))
    25  		rt := getTypeFromPointer(ptr)
    26  		name := rt.Name()
    27  		b.Run(name+":encode", func(b *testing.B) {
    28  			_benchmarkBinary(b, cdc, rt, "binary", true)
    29  		})
    30  		b.Run(name+":decode", func(b *testing.B) {
    31  			_benchmarkBinary(b, cdc, rt, "binary", false)
    32  		})
    33  	}
    34  }
    35  
    36  func BenchmarkBinaryPBBindings(b *testing.B) {
    37  	b.Skip("fuzzing not benchmarking")
    38  
    39  	cdc := amino.NewCodec().WithPBBindings()
    40  	for _, ptr := range tests.StructTypes {
    41  		b.Logf("case %v (pbbindings)", reflect.TypeOf(ptr))
    42  		rt := getTypeFromPointer(ptr)
    43  		name := rt.Name()
    44  		b.Run(name+":encode:pbbindings", func(b *testing.B) {
    45  			_benchmarkBinary(b, cdc, rt, "binary_pb", true)
    46  		})
    47  
    48  		// TODO: fix nil pointer error
    49  		b.Run(name+":encode:pbbindings:translate_only", func(b *testing.B) {
    50  			_benchmarkBinary(b, cdc, rt, "binary_pb_translate_only", true)
    51  		})
    52  
    53  		b.Run(name+":decode:pbbindings", func(b *testing.B) {
    54  			_benchmarkBinary(b, cdc, rt, "binary_pb", false)
    55  		})
    56  
    57  		// TODO: fix nil pointer error
    58  		b.Run(name+":decode:pbbindings:translate_only", func(b *testing.B) {
    59  			_benchmarkBinary(b, cdc, rt, "binary_pb_translate_only", false)
    60  		})
    61  	}
    62  }
    63  
    64  func _benchmarkBinary(b *testing.B, cdc *amino.Codec, rt reflect.Type, codecType string, encode bool) {
    65  	b.Helper()
    66  
    67  	b.StopTimer()
    68  
    69  	err := error(nil)
    70  	bz := []byte{}
    71  	f := fuzz.New()
    72  	pbcdc := cdc.WithPBBindings()
    73  	rv := reflect.New(rt)
    74  	rv2 := reflect.New(rt)
    75  	ptr := rv.Interface()
    76  	ptr2 := rv2.Interface()
    77  	rnd := rand.New(rand.NewSource(10))
    78  	f.RandSource(rnd)
    79  	f.Funcs(fuzzFuncs...)
    80  	pbm := amino.PBMessager(nil)
    81  	pbo := proto.Message(nil)
    82  
    83  	defer func() {
    84  		if r := recover(); r != nil {
    85  			b.Fatalf("panic'd:\nreason: %v\n%s\nerr: %v\nbz: %X\nrv: %#v\nrv2: %#v\nptr: %v\nptr2: %v\n",
    86  				r, debug.Stack(), err, bz, rv, rv2, spw(ptr), spw(ptr2),
    87  			)
    88  		}
    89  	}()
    90  
    91  	for i := 0; i < b.N; i++ {
    92  		f.Fuzz(ptr)
    93  
    94  		// Reset, which makes debugging decoding easier.
    95  		rv2 = reflect.New(rt)
    96  		ptr2 = rv2.Interface()
    97  
    98  		// Encode to bz.
    99  		if encode {
   100  			b.StartTimer()
   101  		}
   102  		switch codecType {
   103  		case "binary":
   104  			bz, err = cdc.Marshal(ptr)
   105  		case "json":
   106  			bz, err = cdc.MarshalJSON(ptr)
   107  		case "binary_pb":
   108  			bz, err = pbcdc.Marshal(ptr)
   109  		case "binary_pb_translate_only":
   110  			pbm, _ = ptr.(amino.PBMessager)
   111  			pbo, err = pbm.ToPBMessage(pbcdc)
   112  		default:
   113  			panic("should not happen")
   114  		}
   115  		if encode {
   116  			b.StopTimer()
   117  		}
   118  
   119  		// Check for errors
   120  		require.Nil(b, err,
   121  			"failed to marshal %v to bytes: %v\n",
   122  			spw(ptr), err)
   123  
   124  		// Decode from bz.
   125  		if !encode {
   126  			b.StartTimer()
   127  		}
   128  		switch codecType {
   129  		case "binary":
   130  			err = cdc.Unmarshal(bz, ptr2)
   131  		case "json":
   132  			err = cdc.UnmarshalJSON(bz, ptr2)
   133  		case "binary_pb":
   134  			err = pbcdc.Unmarshal(bz, ptr2)
   135  		case "binary_pb_translate_only":
   136  			err = pbm.FromPBMessage(pbcdc, pbo)
   137  		default:
   138  			panic("should not happen")
   139  		}
   140  		if !encode {
   141  			b.StopTimer()
   142  		}
   143  
   144  		if codecType != "binary_pb_translate_only" {
   145  			// Decode for completeness and check for errors,
   146  			// in case there were encoding/decoding issues.
   147  			require.NoError(b, err,
   148  				"failed to unmarshal bytes %X (%s): %v\nptr: %v\n",
   149  				bz, bz, err, spw(ptr))
   150  			require.Equal(b, ptr2, ptr,
   151  				"end to end failed.\nstart: %v\nend: %v\nbytes: %X\nstring(bytes): %s\n",
   152  				spw(ptr), spw(ptr2), bz, bz)
   153  		}
   154  	}
   155  }