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 }