github.com/cloudwego/dynamicgo@v0.2.6-0.20240519101509-707f41b6b834/testdata/baseline_p2j_test.go (about) 1 package testdata 2 3 import ( 4 "context" 5 ejson "encoding/json" 6 "errors" 7 "testing" 8 9 "github.com/bytedance/sonic" 10 "github.com/cloudwego/dynamicgo/conv" 11 "github.com/cloudwego/dynamicgo/conv/p2j" 12 "github.com/cloudwego/dynamicgo/proto" 13 "github.com/cloudwego/dynamicgo/testdata/kitex_gen/pb/baseline" 14 "github.com/stretchr/testify/require" 15 "google.golang.org/protobuf/encoding/protowire" 16 ) 17 18 func getPbSimpleDesc() *proto.TypeDescriptor { 19 return proto.FnRequest(proto.GetFnDescFromFile(protoPath, "SimpleMethod", proto.Options{})) 20 } 21 22 func getPbPartialSimpleDesc() *proto.TypeDescriptor { 23 return proto.FnRequest(proto.GetFnDescFromFile(protoPath, "PartialSimpleMethod", proto.Options{})) 24 } 25 26 func getPbNestingDesc() *proto.TypeDescriptor { 27 return proto.FnRequest(proto.GetFnDescFromFile(protoPath, "NestingMethod", proto.Options{})) 28 } 29 30 func getPbPartialNestingDesc() *proto.TypeDescriptor { 31 return proto.FnRequest(proto.GetFnDescFromFile(protoPath, "PartialNestingMethod", proto.Options{})) 32 } 33 34 func FastReadPbSimpleObject(bakBuf []byte, obj *baseline.Simple) error { 35 l := 0 36 datalen := len(bakBuf) 37 for l < datalen { 38 id, wtyp, tagLen := protowire.ConsumeTag(bakBuf) 39 if tagLen < 0 { 40 return errors.New("proto data error format") 41 } 42 l += tagLen 43 bakBuf = bakBuf[tagLen:] 44 offset, err := obj.FastRead(bakBuf, int8(wtyp), int32(id)) 45 if err != nil { 46 return err 47 } 48 bakBuf = bakBuf[offset:] 49 l += offset 50 } 51 if len(bakBuf) != 0 { 52 return errors.New("proto data error format") 53 } 54 return nil 55 } 56 57 func FastReadPbMediumObject(bakBuf []byte, obj *baseline.Nesting) error { 58 l := 0 59 datalen := len(bakBuf) 60 for l < datalen { 61 id, wtyp, tagLen := protowire.ConsumeTag(bakBuf) 62 if tagLen < 0 { 63 return errors.New("proto data error format") 64 } 65 l += tagLen 66 bakBuf = bakBuf[tagLen:] 67 offset, err := obj.FastRead(bakBuf, int8(wtyp), int32(id)) 68 if err != nil { 69 return err 70 } 71 bakBuf = bakBuf[offset:] 72 l += offset 73 } 74 if len(bakBuf) != 0 { 75 return errors.New("proto data error format") 76 } 77 return nil 78 } 79 80 func TestProtobuf2JSON(t *testing.T) { 81 t.Run("small", func(t *testing.T) { 82 ctx := context.Background() 83 desc := getPbSimpleDesc() 84 // kitex to build pbData, and serialize into bytes 85 data := getPbSimpleValue() 86 cv := p2j.NewBinaryConv(conv.Options{}) 87 in := make([]byte, data.Size()) 88 data.FastWrite(in) 89 90 ret, err := cv.Do(ctx, desc, in) 91 if err != nil { 92 t.Fatal(err) 93 } 94 println(string(ret)) 95 96 // unserialize json to object 97 v := &baseline.Simple{} 98 if err := ejson.Unmarshal(ret, v); err != nil { 99 t.Fatal(err) 100 } 101 require.Equal(t, data, v) 102 }) 103 104 t.Run("medium", func(t *testing.T) { 105 ctx := context.Background() 106 desc := getPbNestingDesc() 107 // kitex to build pbData, and serialize into bytes 108 data := getPbNestingValue() 109 cv := p2j.NewBinaryConv(conv.Options{}) 110 in := make([]byte, data.Size()) 111 data.FastWrite(in) 112 113 ret, err := cv.Do(ctx, desc, in) 114 if err != nil { 115 t.Fatal(err) 116 } 117 println(string(ret)) 118 119 // unserialize json to object 120 v := &baseline.Nesting{} 121 if err := ejson.Unmarshal(ret, v); err != nil { 122 t.Fatal(err) 123 } 124 require.Equal(t, data, v) 125 }) 126 } 127 128 func BenchmarkProtobuf2JSON_DynamicGo_Raw(b *testing.B) { 129 b.Run("small", func(b *testing.B) { 130 ctx := context.Background() 131 desc := getPbSimpleDesc() 132 // kitex to build pbData, and serialize into bytes 133 data := getPbSimpleValue() 134 cv := p2j.NewBinaryConv(conv.Options{}) 135 in := make([]byte, data.Size()) 136 data.FastWrite(in) 137 138 _, err := cv.Do(ctx, desc, in) 139 if err != nil { 140 b.Fatal(err) 141 } 142 b.SetBytes(int64(len(in))) 143 b.ResetTimer() 144 for i := 0; i < b.N; i++ { 145 _, _ = cv.Do(ctx, desc, in) 146 } 147 }) 148 149 b.Run("medium", func(b *testing.B) { 150 ctx := context.Background() 151 desc := getPbNestingDesc() 152 // kitex to build pbData, and serialize into bytes 153 data := getPbNestingValue() 154 cv := p2j.NewBinaryConv(conv.Options{}) 155 in := make([]byte, data.Size()) 156 data.FastWrite(in) 157 158 _, err := cv.Do(ctx, desc, in) 159 if err != nil { 160 b.Fatal(err) 161 } 162 b.SetBytes(int64(len(in))) 163 b.ResetTimer() 164 for i := 0; i < b.N; i++ { 165 _, _ = cv.Do(ctx, desc, in) 166 } 167 }) 168 } 169 170 func BenchmarkProtobuf2JSON_SonicAndKitex(b *testing.B) { 171 b.Run("small", func(b *testing.B) { 172 v := getPbSimpleValue() 173 var buf = make([]byte, v.Size()) 174 v.FastWrite(buf) 175 176 // kitex_fastRead build object 177 obj := &baseline.Simple{} 178 if err := FastReadPbSimpleObject(buf, obj); err != nil { 179 b.Fatal(err) 180 } 181 182 // sonic marshal object 183 _, err := sonic.Marshal(obj) 184 if err != nil { 185 b.Fatal(err) 186 } 187 // println(string(out)) 188 189 b.SetBytes(int64(len(buf))) 190 b.ResetTimer() 191 for i := 0; i < b.N; i++ { 192 obj := &baseline.Simple{} 193 _ = FastReadPbSimpleObject(buf, obj) 194 _, _ = sonic.Marshal(obj) 195 } 196 }) 197 198 b.Run("medium", func(b *testing.B) { 199 v := getPbNestingValue() 200 var buf = make([]byte, v.Size()) 201 v.FastWrite(buf) 202 203 // kitex_fastRead build object 204 obj := &baseline.Nesting{} 205 if err := FastReadPbMediumObject(buf, obj); err != nil { 206 b.Fatal(err) 207 } 208 209 // sonic marshal object 210 _, err := sonic.Marshal(obj) 211 if err != nil { 212 b.Fatal(err) 213 } 214 // println(string(out)) 215 216 b.SetBytes(int64(len(buf))) 217 b.ResetTimer() 218 for i := 0; i < b.N; i++ { 219 obj := &baseline.Nesting{} 220 _ = FastReadPbMediumObject(buf, obj) 221 _, _ = sonic.Marshal(obj) 222 } 223 }) 224 } 225 226 // func BenchmarkProtobuf2JSON_ProtoBufGo(b *testing.B) { 227 // b.Run("small", func(b *testing.B) { 228 // data := getPbSimpleValue() 229 // out, err := protojson.Marshal(data.ProtoReflect().Interface()) 230 // if err != nil { 231 // b.Fatal(err) 232 // } 233 // // println(string(out)) 234 235 // b.SetBytes(int64(len(out))) 236 // b.ResetTimer() 237 // for i := 0; i < b.N; i++ { 238 // _, _ = protojson.Marshal(data.ProtoReflect().Interface()) 239 // } 240 // }) 241 242 // b.Run("medium", func(b *testing.B) { 243 // data := getPbNestingValue() 244 // out, err := protojson.Marshal(data.ProtoReflect().Interface()) 245 // if err != nil { 246 // b.Fatal(err) 247 // } 248 // // println(string(out)) 249 250 // b.SetBytes(int64(len(out))) 251 // b.ResetTimer() 252 // for i := 0; i < b.N; i++ { 253 // _, _ = protojson.Marshal(data.ProtoReflect().Interface()) 254 // } 255 // }) 256 // }