github.com/lxt1045/json@v0.0.0-20231013032136-54d6b1d6e525/bench_test.go (about) 1 package json_test 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "io/ioutil" 8 "reflect" 9 "runtime" 10 "strings" 11 "testing" 12 "unsafe" 13 14 "github.com/bytedance/sonic" 15 lxt "github.com/lxt1045/json" 16 "github.com/lxt1045/json/testdata" 17 "github.com/tidwall/gjson" 18 ) 19 20 func BenchmarkIndexByte(b *testing.B) { 21 b.Run("IndexByte", func(b *testing.B) { 22 b.ReportAllocs() 23 for i := 0; i < b.N; i++ { 24 str := testdata.TwitterJsonOut 25 n := 0 26 k := 0 27 for { 28 j := strings.IndexByte(str[k:], '"') 29 if j < 0 { 30 break 31 } 32 n++ 33 k += j + 1 34 } 35 _ = n 36 } 37 b.SetBytes(int64(b.N)) 38 b.StopTimer() 39 }) 40 b.Run("for", func(b *testing.B) { 41 b.ReportAllocs() 42 str := testdata.TwitterJsonOut 43 for i := 0; i < b.N; i++ { 44 n := 0 45 for i := 0; i < len(str); i++ { 46 if str[i] == '"' { 47 n++ 48 } 49 } 50 _ = n 51 } 52 b.SetBytes(int64(b.N)) 53 b.StopTimer() 54 }) 55 } 56 57 func AppendFileToContent(data []string, files ...string) []string { 58 for _, file := range files { 59 bs, err := ioutil.ReadFile(file) 60 if err != nil { 61 panic(err) 62 } 63 data = append(data, BytesToString(bs)) 64 } 65 return data 66 } 67 68 func BenchmarkUnmarshal(b *testing.B) { 69 datas := AppendFileToContent(nil, "./testdata/twitter.json", "./testdata/twitterescaped.json") 70 for i, data := range datas { 71 b.Logf("i:%d,len:%d", i, len(data)) 72 bs := StringToBytes(data) 73 runs := []struct { 74 name string 75 f func() 76 }{ 77 {"std-map", 78 func() { 79 var m map[string]interface{} 80 json.Unmarshal(bs, &m) 81 }, 82 }, 83 {"std-st", 84 func() { 85 var m testdata.Twitter 86 json.Unmarshal(bs, &m) 87 }, 88 }, 89 {"gjson-Parse", 90 func() { 91 gjson.Parse(data).Value() 92 }, 93 }, 94 {"lxt-map", 95 func() { 96 var m map[string]interface{} 97 lxt.UnmarshalString(data, &m) 98 }, 99 }, 100 {"lxt-st", 101 func() { 102 var m testdata.Twitter 103 lxt.UnmarshalString(data, &m) 104 }, 105 }, 106 { 107 "sonic-map", 108 func() { 109 var m map[string]interface{} 110 sonic.UnmarshalString(data, &m) 111 }, 112 }, 113 { 114 "sonic-st", 115 func() { 116 var m testdata.Twitter 117 sonic.UnmarshalString(data, &m) 118 }, 119 }, 120 } 121 var m testdata.Twitter 122 lxt.UnmarshalString(data, &m) 123 for _, r := range runs { 124 b.Run(r.name, func(b *testing.B) { 125 b.ReportAllocs() 126 for i := 0; i < b.N; i++ { 127 r.f() 128 } 129 b.SetBytes(int64(b.N)) 130 b.StopTimer() 131 }) 132 } 133 } 134 } 135 136 func BenchmarkMmarshal(b *testing.B) { 137 datas := AppendFileToContent(nil, "./testdata/twitter.json") 138 var m map[string]interface{} 139 data := datas[0] 140 bs := []byte(data) 141 json.Unmarshal(bs, &m) 142 var st testdata.Twitter 143 json.Unmarshal(bs, &st) 144 runs := []struct { 145 name string 146 f func() 147 }{ 148 {"std-map", 149 func() { 150 json.Marshal(&m) 151 }, 152 }, 153 {"std-st", 154 func() { 155 json.Marshal(&st) 156 }, 157 }, 158 {"lxt-map", 159 func() { 160 lxt.Marshal(&m) 161 }, 162 }, 163 {"lxt-st", 164 func() { 165 lxt.Marshal(&st) 166 }, 167 }, 168 { 169 "sonic-map", 170 func() { 171 sonic.Marshal(&m) 172 }, 173 }, 174 { 175 "sonic-st", 176 func() { 177 sonic.Marshal(&st) 178 }, 179 }, 180 } 181 for _, r := range runs { 182 b.Run(r.name, func(b *testing.B) { 183 b.ReportAllocs() 184 for i := 0; i < b.N; i++ { 185 r.f() 186 } 187 b.SetBytes(int64(b.N)) 188 b.StopTimer() 189 }) 190 } 191 } 192 193 //BytesToString ... 194 func BytesToString(b []byte) string { 195 return *(*string)(unsafe.Pointer(&b)) 196 } 197 198 //StringToBytes ... 199 func StringToBytes(s string) []byte { 200 strH := (*reflect.StringHeader)(unsafe.Pointer(&s)) 201 p := reflect.SliceHeader{ 202 Data: strH.Data, 203 Len: strH.Len, 204 Cap: strH.Len, 205 } 206 return *(*[]byte)(unsafe.Pointer(&p)) 207 } 208 209 /* 210 go test -benchmem -run=^$ -v -benchtime=10000000x -bench ^BenchmarkUnmarshalType$ github.com/lxt1045/json -count=1 211 212 go test -benchmem -run=^$ -bench ^BenchmarkUnmarshalType$ github.com/lxt1045/json -count=1 -v -cpuprofile cpu.prof -c 213 go test -benchmem -run=^$ -bench ^BenchmarkUnmarshalType$ github.com/lxt1045/json -count=1 -v -memprofile cpu.prof -c 214 go tool pprof ./json.test cpu.prof 215 */ 216 217 func BenchmarkUnmarshalType(b *testing.B) { 218 type X struct { 219 A string 220 B string 221 } 222 type Y struct { 223 A bool 224 B bool 225 } 226 all := []struct { 227 V interface{} 228 JsonV string 229 }{ 230 {uint(0), `888888`}, // 0 231 {(*uint)(nil), `888888`}, // 1 232 {int8(0), `88`}, // 2 233 {int(0), `888888`}, // 3 234 {true, `true`}, // 4 235 {"", `"asdfghjkl"`}, // 5 236 {[]int8{}, `[1,2,3]`}, // 6 237 {[]int{}, `[1,2,3]`}, // 7 238 {[]bool{}, `[true,true,true]`}, // 8 239 {[]string{}, `["1","2","3"]`}, // 9 240 {[]X{}, `[{"A":"aaaa","B":"bbbb"},{"A":"aaaa","B":"bbbb"},{"A":"aaaa","B":"bbbb"}]`}, 241 {[]Y{}, `[{"A":true,"B":true},{"A":true,"B":true},{"A":true,"B":true}]`}, 242 {(*int)(nil), `88`}, // 11 243 {(*bool)(nil), `true`}, // 12 244 {(*string)(nil), `"asdfghjkl"`}, // 13 245 } 246 N := 10 247 idxs := []int{} 248 // idxs = []int{10} 249 if len(idxs) > 0 { 250 get := all[:0] 251 for _, i := range idxs { 252 get = append(get, all[i]) 253 } 254 all = get 255 } 256 var err error 257 for _, obj := range all { 258 builder := lxt.NewTypeBuilder() 259 buf := bytes.NewBufferString("{") 260 fieldType := reflect.TypeOf(obj.V) 261 for i := 0; i < N; i++ { 262 if i != 0 { 263 buf.WriteByte(',') 264 } 265 key := fmt.Sprintf("Field_%d", i) 266 builder.AddField(key, fieldType) 267 buf.WriteString(fmt.Sprintf(`"%s":%v`, key, obj.JsonV)) 268 } 269 buf.WriteByte('}') 270 bs := buf.Bytes() 271 str := string(bs) 272 273 // b.Logf("json:%s", str) 274 typ := builder.Build() 275 value := reflect.New(typ).Interface() 276 // b.Logf("\ntype:%T\n", value) 277 278 runtime.GC() 279 b.Run(fmt.Sprintf("%s-%d-lxt", fieldType, N), func(b *testing.B) { 280 b.SetBytes(int64(len(str))) 281 b.ResetTimer() 282 for i := 0; i < b.N; i++ { 283 err := lxt.UnmarshalString(str, value) 284 if err != nil { 285 b.Fatal(err) 286 } 287 } 288 }) 289 // continue 290 runtime.GC() 291 b.Run(fmt.Sprintf("%s-%d-sonic", fieldType, N), func(b *testing.B) { 292 b.SetBytes(int64(len(str))) 293 b.ResetTimer() 294 for i := 0; i < b.N; i++ { 295 err := sonic.UnmarshalString(str, value) 296 if err != nil { 297 b.Fatal(err) 298 } 299 } 300 }) 301 // runtime.GC() 302 // b.Run(fmt.Sprintf("%s-%d-lxt", fieldType, N), func(b *testing.B) { 303 // for i := 0; i < b.N; i++ { 304 // err := lxt.UnmarshalString(str, value) 305 // if err != nil { 306 // b.Fatal(err) 307 // } 308 // } 309 // }) 310 311 // continue 312 // runtime.GC() 313 // b.Run(fmt.Sprintf("%s-%d-std", fieldType, N), func(b *testing.B) { 314 // for i := 0; i < b.N; i++ { 315 // err := json.Unmarshal(bs, value) 316 // if err != nil { 317 // b.Fatal(err) 318 // } 319 // } 320 // }) 321 322 runtime.GC() 323 b.Run(fmt.Sprintf("Marshal-%s-%d-lxt", fieldType, N), func(b *testing.B) { 324 b.SetBytes(int64(len(str))) 325 b.ResetTimer() 326 for i := 0; i < b.N; i++ { 327 bs, err = lxt.Marshal(value) 328 if err != nil { 329 b.Fatal(err) 330 } 331 } 332 }) 333 runtime.GC() 334 b.Run(fmt.Sprintf("Marshal-%s-%d-sonic", fieldType, N), func(b *testing.B) { 335 b.SetBytes(int64(len(str))) 336 b.ResetTimer() 337 for i := 0; i < b.N; i++ { 338 bs, err = sonic.Marshal(value) 339 if err != nil { 340 b.Fatal(err) 341 } 342 } 343 }) 344 // runtime.GC() 345 // b.Run(fmt.Sprintf("Marshal-%s-%d-std", fieldType, N), func(b *testing.B) { 346 // for i := 0; i < b.N; i++ { 347 // bs, err = json.Marshal(value) 348 // if err != nil { 349 // b.Fatal(err) 350 // } 351 // } 352 // }) 353 } 354 } 355 356 // 357 358 func BenchmarkSmallBinding(b *testing.B) { 359 bs := []byte(testdata.BookData) 360 str := string(bs) 361 d := testdata.Book{} 362 err := lxt.Unmarshal(bs, &d) 363 if err != nil { 364 b.Fatal(err) 365 } 366 sonic.UnmarshalString(str, &d) 367 368 runtime.GC() 369 b.Run("decode-lxt", func(b *testing.B) { 370 b.SetBytes(int64(len(bs))) 371 // b.ReportAllocs() 372 b.ResetTimer() 373 for i := 0; i < b.N; i++ { 374 d := testdata.Book{} 375 _ = lxt.UnmarshalString(str, &d) 376 } 377 }) 378 379 runtime.GC() 380 b.Run("decode-sonic", func(b *testing.B) { 381 b.SetBytes(int64(len(bs))) 382 b.ResetTimer() 383 for i := 0; i < b.N; i++ { 384 d := testdata.Book{} 385 _ = sonic.UnmarshalString(str, &d) 386 } 387 }) 388 389 runtime.GC() 390 b.Run("decode-parallel-lxt", func(b *testing.B) { 391 b.SetBytes(int64(len(bs))) 392 // b.ReportAllocs() 393 b.ResetTimer() 394 b.RunParallel(func(pb *testing.PB) { 395 for pb.Next() { 396 d := testdata.Book{} 397 _ = lxt.UnmarshalString(str, &d) 398 } 399 }) 400 }) 401 402 runtime.GC() 403 b.Run("decode-parallel-sonic", func(b *testing.B) { 404 b.SetBytes(int64(len(bs))) 405 b.ResetTimer() 406 b.RunParallel(func(pb *testing.PB) { 407 for pb.Next() { 408 d := testdata.Book{} 409 _ = sonic.UnmarshalString(str, &d) 410 } 411 }) 412 }) 413 414 // encode 415 416 runtime.GC() 417 b.Run("encode-lxt", func(b *testing.B) { 418 b.SetBytes(int64(len(bs))) 419 // b.ReportAllocs() 420 b.ResetTimer() 421 for i := 0; i < b.N; i++ { 422 _, _ = lxt.Marshal(&d) 423 } 424 }) 425 426 runtime.GC() 427 b.Run("encode-sonic", func(b *testing.B) { 428 b.SetBytes(int64(len(bs))) 429 b.ResetTimer() 430 for i := 0; i < b.N; i++ { 431 _, _ = sonic.Marshal(&d) 432 } 433 }) 434 435 runtime.GC() 436 b.Run("encode-parallel-lxt", func(b *testing.B) { 437 b.SetBytes(int64(len(bs))) 438 // b.ReportAllocs() 439 b.ResetTimer() 440 b.RunParallel(func(pb *testing.PB) { 441 for pb.Next() { 442 _, _ = lxt.Marshal(&d) 443 } 444 }) 445 }) 446 447 runtime.GC() 448 b.Run("encode-parallel-sonic", func(b *testing.B) { 449 b.SetBytes(int64(len(bs))) 450 b.ResetTimer() 451 b.RunParallel(func(pb *testing.PB) { 452 for pb.Next() { 453 _, _ = sonic.Marshal(&d) 454 } 455 }) 456 }) 457 } 458 459 func BenchmarkSmallGeneric(b *testing.B) { 460 bs := []byte(testdata.BookData) 461 str := string(bs) 462 var d interface{} 463 err := lxt.Unmarshal(bs, &d) 464 if err != nil { 465 b.Fatal(err) 466 } 467 sonic.UnmarshalString(str, &d) 468 469 runtime.GC() 470 b.Run("decode-lxt", func(b *testing.B) { 471 b.SetBytes(int64(len(bs))) 472 // b.ReportAllocs() 473 b.ResetTimer() 474 for i := 0; i < b.N; i++ { 475 var d interface{} 476 _ = lxt.UnmarshalString(str, &d) 477 } 478 }) 479 480 runtime.GC() 481 b.Run("decode-sonic", func(b *testing.B) { 482 b.SetBytes(int64(len(bs))) 483 b.ResetTimer() 484 for i := 0; i < b.N; i++ { 485 var d interface{} 486 _ = sonic.UnmarshalString(str, &d) 487 } 488 }) 489 490 runtime.GC() 491 b.Run("decode-parallel-lxt", func(b *testing.B) { 492 b.SetBytes(int64(len(bs))) 493 // b.ReportAllocs() 494 b.ResetTimer() 495 b.RunParallel(func(pb *testing.PB) { 496 for pb.Next() { 497 var d interface{} 498 _ = lxt.UnmarshalString(str, &d) 499 } 500 }) 501 }) 502 503 runtime.GC() 504 b.Run("decode-parallel-sonic", func(b *testing.B) { 505 b.SetBytes(int64(len(bs))) 506 b.ResetTimer() 507 b.RunParallel(func(pb *testing.PB) { 508 for pb.Next() { 509 var d interface{} 510 _ = sonic.UnmarshalString(str, &d) 511 } 512 }) 513 }) 514 515 // encode 516 517 runtime.GC() 518 b.Run("encode-lxt", func(b *testing.B) { 519 b.SetBytes(int64(len(bs))) 520 // b.ReportAllocs() 521 b.ResetTimer() 522 for i := 0; i < b.N; i++ { 523 _, _ = lxt.Marshal(&d) 524 } 525 }) 526 527 runtime.GC() 528 b.Run("encode-sonic", func(b *testing.B) { 529 b.SetBytes(int64(len(bs))) 530 b.ResetTimer() 531 for i := 0; i < b.N; i++ { 532 _, _ = sonic.Marshal(&d) 533 } 534 }) 535 536 runtime.GC() 537 b.Run("encode-parallel-lxt", func(b *testing.B) { 538 b.SetBytes(int64(len(bs))) 539 // b.ReportAllocs() 540 b.ResetTimer() 541 b.RunParallel(func(pb *testing.PB) { 542 for pb.Next() { 543 _, _ = lxt.Marshal(&d) 544 } 545 }) 546 }) 547 548 runtime.GC() 549 b.Run("encode-parallel-sonic", func(b *testing.B) { 550 b.SetBytes(int64(len(bs))) 551 b.ResetTimer() 552 b.RunParallel(func(pb *testing.PB) { 553 for pb.Next() { 554 _, _ = sonic.Marshal(&d) 555 } 556 }) 557 }) 558 } 559 560 func BenchmarkMediumBinding(b *testing.B) { 561 bs := []byte(testdata.TwitterJson) 562 str := string(bs) 563 d := testdata.TwitterStruct{} 564 err := lxt.Unmarshal(bs, &d) 565 if err != nil { 566 b.Fatal(err) 567 } 568 sonic.UnmarshalString(str, &d) 569 570 runtime.GC() 571 b.Run("decode-lxt", func(b *testing.B) { 572 b.SetBytes(int64(len(bs))) 573 // b.ReportAllocs() 574 b.ResetTimer() 575 for i := 0; i < b.N; i++ { 576 d := testdata.TwitterStruct{} 577 _ = lxt.UnmarshalString(str, &d) 578 } 579 }) 580 581 runtime.GC() 582 b.Run("decode-sonic", func(b *testing.B) { 583 b.SetBytes(int64(len(bs))) 584 b.ResetTimer() 585 for i := 0; i < b.N; i++ { 586 d := testdata.TwitterStruct{} 587 _ = sonic.UnmarshalString(str, &d) 588 } 589 }) 590 591 runtime.GC() 592 b.Run("decode-parallel-lxt", func(b *testing.B) { 593 b.SetBytes(int64(len(bs))) 594 // b.ReportAllocs() 595 b.ResetTimer() 596 b.RunParallel(func(pb *testing.PB) { 597 for pb.Next() { 598 d := testdata.TwitterStruct{} 599 _ = lxt.UnmarshalString(str, &d) 600 } 601 }) 602 }) 603 604 runtime.GC() 605 b.Run("decode-parallel-sonic", func(b *testing.B) { 606 b.SetBytes(int64(len(bs))) 607 b.ResetTimer() 608 b.RunParallel(func(pb *testing.PB) { 609 for pb.Next() { 610 d := testdata.TwitterStruct{} 611 _ = sonic.UnmarshalString(str, &d) 612 } 613 }) 614 }) 615 616 // encode 617 618 runtime.GC() 619 b.Run("encode-lxt", func(b *testing.B) { 620 b.SetBytes(int64(len(bs))) 621 // b.ReportAllocs() 622 b.ResetTimer() 623 for i := 0; i < b.N; i++ { 624 _, _ = lxt.Marshal(&d) 625 } 626 }) 627 628 runtime.GC() 629 b.Run("encode-sonic", func(b *testing.B) { 630 b.SetBytes(int64(len(bs))) 631 b.ResetTimer() 632 for i := 0; i < b.N; i++ { 633 _, _ = sonic.Marshal(&d) 634 } 635 }) 636 637 runtime.GC() 638 b.Run("encode-parallel-lxt", func(b *testing.B) { 639 b.SetBytes(int64(len(bs))) 640 // b.ReportAllocs() 641 b.ResetTimer() 642 b.RunParallel(func(pb *testing.PB) { 643 for pb.Next() { 644 _, _ = lxt.Marshal(&d) 645 } 646 }) 647 }) 648 649 runtime.GC() 650 b.Run("encode-parallel-sonic", func(b *testing.B) { 651 b.SetBytes(int64(len(bs))) 652 b.ResetTimer() 653 b.RunParallel(func(pb *testing.PB) { 654 for pb.Next() { 655 _, _ = sonic.Marshal(&d) 656 } 657 }) 658 }) 659 } 660 661 func BenchmarkMediumGeneric(b *testing.B) { 662 bs := []byte(testdata.TwitterJson) 663 str := string(bs) 664 var d interface{} 665 err := lxt.Unmarshal(bs, &d) 666 if err != nil { 667 b.Fatal(err) 668 } 669 sonic.UnmarshalString(str, &d) 670 671 runtime.GC() 672 b.Run("decode-lxt", func(b *testing.B) { 673 b.SetBytes(int64(len(bs))) 674 // b.ReportAllocs() 675 b.ResetTimer() 676 for i := 0; i < b.N; i++ { 677 var d interface{} 678 _ = lxt.UnmarshalString(str, &d) 679 } 680 }) 681 682 runtime.GC() 683 b.Run("decode-sonic", func(b *testing.B) { 684 b.SetBytes(int64(len(bs))) 685 b.ResetTimer() 686 for i := 0; i < b.N; i++ { 687 var d interface{} 688 _ = sonic.UnmarshalString(str, &d) 689 } 690 }) 691 692 runtime.GC() 693 b.Run("decode-parallel-lxt", func(b *testing.B) { 694 b.SetBytes(int64(len(bs))) 695 // b.ReportAllocs() 696 b.ResetTimer() 697 b.RunParallel(func(pb *testing.PB) { 698 for pb.Next() { 699 var d interface{} 700 _ = lxt.UnmarshalString(str, &d) 701 } 702 }) 703 }) 704 705 runtime.GC() 706 b.Run("decode-parallel-sonic", func(b *testing.B) { 707 b.SetBytes(int64(len(bs))) 708 b.ResetTimer() 709 b.RunParallel(func(pb *testing.PB) { 710 for pb.Next() { 711 var d interface{} 712 _ = sonic.UnmarshalString(str, &d) 713 } 714 }) 715 }) 716 717 // encode 718 719 runtime.GC() 720 b.Run("encode-lxt", func(b *testing.B) { 721 b.SetBytes(int64(len(bs))) 722 // b.ReportAllocs() 723 b.ResetTimer() 724 for i := 0; i < b.N; i++ { 725 _, _ = lxt.Marshal(&d) 726 } 727 }) 728 729 runtime.GC() 730 b.Run("encode-sonic", func(b *testing.B) { 731 b.SetBytes(int64(len(bs))) 732 b.ResetTimer() 733 for i := 0; i < b.N; i++ { 734 _, _ = sonic.Marshal(&d) 735 } 736 }) 737 738 runtime.GC() 739 b.Run("encode-parallel-lxt", func(b *testing.B) { 740 b.SetBytes(int64(len(bs))) 741 // b.ReportAllocs() 742 b.ResetTimer() 743 b.RunParallel(func(pb *testing.PB) { 744 for pb.Next() { 745 _, _ = lxt.Marshal(&d) 746 } 747 }) 748 }) 749 750 runtime.GC() 751 b.Run("encode-parallel-sonic", func(b *testing.B) { 752 b.SetBytes(int64(len(bs))) 753 b.ResetTimer() 754 b.RunParallel(func(pb *testing.PB) { 755 for pb.Next() { 756 _, _ = sonic.Marshal(&d) 757 } 758 }) 759 }) 760 } 761 762 func BenchmarkLargeBinding(b *testing.B) { 763 bs := []byte(testdata.TwitterJsonLarge) 764 str := string(bs) 765 d := testdata.TwitterStruct{} 766 err := lxt.Unmarshal(bs, &d) 767 if err != nil { 768 b.Fatal(err) 769 } 770 sonic.UnmarshalString(str, &d) 771 772 runtime.GC() 773 b.Run("decode-lxt", func(b *testing.B) { 774 b.SetBytes(int64(len(bs))) 775 // b.ReportAllocs() 776 b.ResetTimer() 777 for i := 0; i < b.N; i++ { 778 d := testdata.TwitterStruct{} 779 _ = lxt.UnmarshalString(str, &d) 780 } 781 }) 782 783 runtime.GC() 784 b.Run("decode-sonic", func(b *testing.B) { 785 b.SetBytes(int64(len(bs))) 786 b.ResetTimer() 787 for i := 0; i < b.N; i++ { 788 d := testdata.TwitterStruct{} 789 _ = sonic.UnmarshalString(str, &d) 790 } 791 }) 792 793 runtime.GC() 794 b.Run("decode-parallel-lxt", func(b *testing.B) { 795 b.SetBytes(int64(len(bs))) 796 // b.ReportAllocs() 797 b.ResetTimer() 798 b.RunParallel(func(pb *testing.PB) { 799 for pb.Next() { 800 d := testdata.TwitterStruct{} 801 _ = lxt.UnmarshalString(str, &d) 802 } 803 }) 804 }) 805 806 runtime.GC() 807 b.Run("decode-parallel-sonic", func(b *testing.B) { 808 b.SetBytes(int64(len(bs))) 809 b.ResetTimer() 810 b.RunParallel(func(pb *testing.PB) { 811 for pb.Next() { 812 d := testdata.TwitterStruct{} 813 _ = sonic.UnmarshalString(str, &d) 814 } 815 }) 816 }) 817 818 // encode 819 820 runtime.GC() 821 b.Run("encode-lxt", func(b *testing.B) { 822 b.SetBytes(int64(len(bs))) 823 // b.ReportAllocs() 824 b.ResetTimer() 825 for i := 0; i < b.N; i++ { 826 _, _ = lxt.Marshal(&d) 827 } 828 }) 829 830 runtime.GC() 831 b.Run("encode-sonic", func(b *testing.B) { 832 b.SetBytes(int64(len(bs))) 833 b.ResetTimer() 834 for i := 0; i < b.N; i++ { 835 _, _ = sonic.Marshal(&d) 836 } 837 }) 838 839 runtime.GC() 840 b.Run("encode-parallel-lxt", func(b *testing.B) { 841 b.SetBytes(int64(len(bs))) 842 // b.ReportAllocs() 843 b.ResetTimer() 844 b.RunParallel(func(pb *testing.PB) { 845 for pb.Next() { 846 _, _ = lxt.Marshal(&d) 847 } 848 }) 849 }) 850 851 runtime.GC() 852 b.Run("encode-parallel-sonic", func(b *testing.B) { 853 b.SetBytes(int64(len(bs))) 854 b.ResetTimer() 855 b.RunParallel(func(pb *testing.PB) { 856 for pb.Next() { 857 _, _ = sonic.Marshal(&d) 858 } 859 }) 860 }) 861 } 862 863 func BenchmarkLargeGeneric(b *testing.B) { 864 bs := []byte(testdata.TwitterJsonLarge) 865 str := string(bs) 866 var d interface{} 867 err := lxt.Unmarshal(bs, &d) 868 if err != nil { 869 b.Fatal(err) 870 } 871 sonic.UnmarshalString(str, &d) 872 873 runtime.GC() 874 b.Run("decode-lxt", func(b *testing.B) { 875 b.SetBytes(int64(len(bs))) 876 // b.ReportAllocs() 877 b.ResetTimer() 878 for i := 0; i < b.N; i++ { 879 var d interface{} 880 _ = lxt.UnmarshalString(str, &d) 881 } 882 }) 883 884 runtime.GC() 885 b.Run("decode-sonic", func(b *testing.B) { 886 b.SetBytes(int64(len(bs))) 887 b.ResetTimer() 888 for i := 0; i < b.N; i++ { 889 var d interface{} 890 _ = sonic.UnmarshalString(str, &d) 891 } 892 }) 893 894 runtime.GC() 895 b.Run("decode-parallel-lxt", func(b *testing.B) { 896 b.SetBytes(int64(len(bs))) 897 // b.ReportAllocs() 898 b.ResetTimer() 899 b.RunParallel(func(pb *testing.PB) { 900 for pb.Next() { 901 var d interface{} 902 _ = lxt.UnmarshalString(str, &d) 903 } 904 }) 905 }) 906 907 runtime.GC() 908 b.Run("decode-parallel-sonic", func(b *testing.B) { 909 b.SetBytes(int64(len(bs))) 910 b.ResetTimer() 911 b.RunParallel(func(pb *testing.PB) { 912 for pb.Next() { 913 var d interface{} 914 _ = sonic.UnmarshalString(str, &d) 915 } 916 }) 917 }) 918 919 // encode 920 921 runtime.GC() 922 b.Run("encode-lxt", func(b *testing.B) { 923 b.SetBytes(int64(len(bs))) 924 // b.ReportAllocs() 925 b.ResetTimer() 926 for i := 0; i < b.N; i++ { 927 _, _ = lxt.Marshal(&d) 928 } 929 }) 930 931 runtime.GC() 932 b.Run("encode-sonic", func(b *testing.B) { 933 b.SetBytes(int64(len(bs))) 934 b.ResetTimer() 935 for i := 0; i < b.N; i++ { 936 _, _ = sonic.Marshal(&d) 937 } 938 }) 939 940 runtime.GC() 941 b.Run("encode-parallel-lxt", func(b *testing.B) { 942 b.SetBytes(int64(len(bs))) 943 // b.ReportAllocs() 944 b.ResetTimer() 945 b.RunParallel(func(pb *testing.PB) { 946 for pb.Next() { 947 _, _ = lxt.Marshal(&d) 948 } 949 }) 950 }) 951 952 runtime.GC() 953 b.Run("encode-parallel-sonic", func(b *testing.B) { 954 b.SetBytes(int64(len(bs))) 955 b.ResetTimer() 956 b.RunParallel(func(pb *testing.PB) { 957 for pb.Next() { 958 _, _ = sonic.Marshal(&d) 959 } 960 }) 961 }) 962 } 963 964 // 965 966 func BenchmarkUnmarshalInterface(b *testing.B) { 967 968 all := []struct { 969 V interface{} 970 JsonV string 971 }{ 972 {int(0), `888888`}, 973 {true, `true`}, 974 {"", `"asdfghjkl"`}, 975 } 976 N := 10 977 var value = &struct { 978 Field_0 interface{} 979 Field_1 interface{} 980 Field_2 interface{} 981 Field_3 interface{} 982 Field_4 interface{} 983 Field_5 interface{} 984 Field_6 interface{} 985 Field_7 interface{} 986 Field_8 interface{} 987 Field_9 interface{} 988 }{} 989 for _, obj := range all { 990 buf := bytes.NewBufferString("{") 991 for i := 0; i < N; i++ { 992 if i != 0 { 993 buf.WriteByte(',') 994 } 995 key := fmt.Sprintf("Field_%d", i) 996 buf.WriteString(fmt.Sprintf(`"%s":%s`, key, obj.JsonV)) 997 } 998 buf.WriteByte('}') 999 bs := buf.Bytes() 1000 str := string(bs) 1001 fieldType := reflect.TypeOf(obj.V) 1002 1003 b.Run(fmt.Sprintf("%s-%d-lxt", fieldType, N), func(b *testing.B) { 1004 for i := 0; i < b.N; i++ { 1005 err := lxt.UnmarshalString(str, value) 1006 if err != nil { 1007 b.Fatal(err) 1008 } 1009 } 1010 }) 1011 b.Run(fmt.Sprintf("%s-%d-sonic", fieldType, N), func(b *testing.B) { 1012 for i := 0; i < b.N; i++ { 1013 err := sonic.UnmarshalString(str, value) 1014 if err != nil { 1015 b.Fatal(err) 1016 } 1017 } 1018 }) 1019 b.Run(fmt.Sprintf("%s-%d-std", fieldType, N), func(b *testing.B) { 1020 for i := 0; i < b.N; i++ { 1021 err := json.Unmarshal(bs, value) 1022 if err != nil { 1023 b.Fatal(err) 1024 } 1025 } 1026 }) 1027 1028 var err error 1029 b.Run(fmt.Sprintf("Marshal-%s-%d-lxt", fieldType, N), func(b *testing.B) { 1030 for i := 0; i < b.N; i++ { 1031 bs, err = lxt.Marshal(value) 1032 if err != nil { 1033 b.Fatal(err) 1034 } 1035 } 1036 }) 1037 b.Run(fmt.Sprintf("Marshal-%s-%d-sonic", fieldType, N), func(b *testing.B) { 1038 for i := 0; i < b.N; i++ { 1039 bs, err = sonic.Marshal(value) 1040 if err != nil { 1041 b.Fatal(err) 1042 } 1043 } 1044 }) 1045 b.Run(fmt.Sprintf("Marshal-%s-%d-std", fieldType, N), func(b *testing.B) { 1046 for i := 0; i < b.N; i++ { 1047 bs, err = json.Marshal(value) 1048 if err != nil { 1049 b.Fatal(err) 1050 } 1051 } 1052 }) 1053 } 1054 } 1055 1056 func BenchmarkUnmarshalMapInterface(b *testing.B) { 1057 all := []struct { 1058 V interface{} 1059 JsonV string 1060 }{ 1061 {int(0), `888888`}, 1062 {true, `true`}, 1063 {"", `"asdfghjkl"`}, 1064 } 1065 N := 10 1066 var value = &map[string]interface{}{} 1067 for _, obj := range all { 1068 buf := bytes.NewBufferString("{") 1069 for i := 0; i < N; i++ { 1070 if i != 0 { 1071 buf.WriteByte(',') 1072 } 1073 key := fmt.Sprintf("Field_%d", i) 1074 buf.WriteString(fmt.Sprintf(`"%s":%s`, key, obj.JsonV)) 1075 } 1076 buf.WriteByte('}') 1077 bs := buf.Bytes() 1078 str := string(bs) 1079 fieldType := reflect.TypeOf(obj.V) 1080 1081 b.Run(fmt.Sprintf("%s-%d-lxt", fieldType, N), func(b *testing.B) { 1082 for i := 0; i < b.N; i++ { 1083 err := lxt.UnmarshalString(str, value) 1084 if err != nil { 1085 b.Fatal(err) 1086 } 1087 } 1088 }) 1089 b.Run(fmt.Sprintf("%s-%d-sonic", fieldType, N), func(b *testing.B) { 1090 for i := 0; i < b.N; i++ { 1091 err := sonic.UnmarshalString(str, value) 1092 if err != nil { 1093 b.Fatal(err) 1094 } 1095 } 1096 }) 1097 b.Run(fmt.Sprintf("%s-%d-std", fieldType, N), func(b *testing.B) { 1098 for i := 0; i < b.N; i++ { 1099 err := json.Unmarshal(bs, value) 1100 if err != nil { 1101 b.Fatal(err) 1102 } 1103 } 1104 }) 1105 1106 var err error 1107 b.Run(fmt.Sprintf("Marshal-%s-%d-lxt", fieldType, N), func(b *testing.B) { 1108 for i := 0; i < b.N; i++ { 1109 bs, err = lxt.Marshal(value) 1110 if err != nil { 1111 b.Fatal(err) 1112 } 1113 } 1114 }) 1115 b.Run(fmt.Sprintf("Marshal-%s-%d-sonic", fieldType, N), func(b *testing.B) { 1116 for i := 0; i < b.N; i++ { 1117 bs, err = sonic.Marshal(value) 1118 if err != nil { 1119 b.Fatal(err) 1120 } 1121 } 1122 }) 1123 b.Run(fmt.Sprintf("Marshal-%s-%d-std", fieldType, N), func(b *testing.B) { 1124 for i := 0; i < b.N; i++ { 1125 bs, err = json.Marshal(value) 1126 if err != nil { 1127 b.Fatal(err) 1128 } 1129 } 1130 }) 1131 } 1132 } 1133 1134 // TODO: slice 1135 /* 1136 go test -benchmem -run=^$ -bench ^BenchmarkObj$ github.com/lxt1045/json -count=1 -v -cpuprofile cpu.prof -c 1137 go test -benchmem -run=^$ -bench ^BenchmarkObj$ github.com/lxt1045/json -count=1 -v -memprofile cpu.prof -c 1138 go tool pprof ./json.test cpu.prof 1139 // */ 1140 func BenchmarkStrings(b *testing.B) { 1141 // str := `{"X0":["1","2","3"]}` 1142 // str := `{"X0":["1","2","3","2","3","2","3","2","3","2","3","2","3","2","3","2","3","2","3","2","3","2","3"],"X1":["1","2","3","2","3","2","3","2","3","2","3","2","3"],"X2":["1","2","3","2","3","2","3","2","3","2","3","2","3"],"X3":["1","2","3","2","3","2","3","2","3","2","3","2","3"],"X4":["1","2","3","2","3","2","3","2","3","2","3","2","3"],"X5":["1","2","3","2","3","2","3","2","3","2","3","2","3"],"X6":["1","2","3","2","3","2","3","2","3","2","3","2","3"],"X7":["1","2","3","2","3","2","3","2","3","2","3","2","3"],"X8":["1","2","3","2","3","2","3","2","3","2","3","2","3"],"X9":["1","2","3","2","3","2","3","2","3","2","3","2","3"]}` 1143 str := `{"X0":["1","2","3"],"X1":["1","2","3"],"X2":["1","2","3"],"X3":["1","2","3"],"X4":["1","2","3"],"X5":["1","2","3"],"X6":["1","2","3"],"X7":["1","2","3"],"X8":["1","2","3"],"X9":["1","2","3"]}` 1144 // str := `{"X0":["1","2","3","2","3","2","3","2","3","2","3","2","3","2","3","2","3","2","3","2","3","2","3","2","3","2","3","2","3","2","3"]}` 1145 // str := `{"X0":["1","2","3","2","3","1","2","3","2","3"]}` 1146 d := struct { 1147 X0 []string 1148 X1 []string 1149 X2 []string 1150 X3 []string 1151 X4 []string 1152 X5 []string 1153 X6 []string 1154 X7 []string 1155 X8 []string 1156 X9 []string 1157 }{} 1158 b.Run("lxt-strings", func(b *testing.B) { 1159 b.ReportAllocs() 1160 for i := 0; i < b.N; i++ { 1161 err := lxt.UnmarshalString(str, &d) 1162 if err != nil { 1163 b.Fatalf("[%d]:%v", i, err) 1164 } 1165 } 1166 b.StopTimer() 1167 b.SetBytes(int64(b.N)) 1168 }) 1169 // return 1170 b.Run("sonic-strings", func(b *testing.B) { 1171 b.ReportAllocs() 1172 for i := 0; i < b.N; i++ { 1173 err := sonic.UnmarshalString(str, &d) 1174 if err != nil { 1175 b.Fatalf("[%d]:%v", i, err) 1176 } 1177 } 1178 b.StopTimer() 1179 b.SetBytes(int64(b.N)) 1180 }) 1181 } 1182 1183 /* 1184 1185 BenchmarkObj/lxt-obj 1186 BenchmarkObj/lxt-obj-12 394314 3049 ns/op 129330.79 MB/s 1286 B/op 0 allocs/op 1187 BenchmarkObj/sonic-obj 1188 BenchmarkObj/sonic-obj-12 357523 2850 ns/op 125466.19 MB/s 4 B/op 0 allocs/op 1189 */ 1190 func BenchmarkObj(b *testing.B) { 1191 str := `{"X0":[{"A":"1","B":"2"},{"A":"1","B":"2"},{"A":"1","B":"2"}],"X1":[{"A":"1","B":"2"},{"A":"1","B":"2"},{"A":"1","B":"2"}],"X2":[{"A":"1","B":"2"},{"A":"1","B":"2"},{"A":"1","B":"2"}],"X3":[{"A":"1","B":"2"},{"A":"1","B":"2"},{"A":"1","B":"2"}],"X4":[{"A":"1","B":"2"},{"A":"1","B":"2"},{"A":"1","B":"2"}],"X5":[{"A":"1","B":"2"},{"A":"1","B":"2"},{"A":"1","B":"2"}],"X6":[{"A":"1","B":"2"},{"A":"1","B":"2"},{"A":"1","B":"2"}],"X7":[{"A":"1","B":"2"},{"A":"1","B":"2"},{"A":"1","B":"2"}],"X8":[{"A":"1","B":"2"},{"A":"1","B":"2"},{"A":"1","B":"2"}],"X9":[{"A":"1","B":"2"},{"A":"1","B":"2"},{"A":"1","B":"2"}]}` 1192 // str := `{"X0":[{"A":"1","B":"2"},{"A":"1","B":"2"},{"A":"1","B":"2"}]}` 1193 type X struct { 1194 A string 1195 B string 1196 C *int 1197 } 1198 d := struct { 1199 X0 []X 1200 X1 []X 1201 X2 []X 1202 X3 []X 1203 X4 []X 1204 X5 []X 1205 X6 []X 1206 X7 []X 1207 X8 []X 1208 X9 []X 1209 }{} 1210 // err := lxt.UnmarshalString(str, &d) 1211 // if err != nil { 1212 // b.Fatalf("[%d]:%v", 0, err) 1213 // } 1214 // b.Logf("json:%+v", d) 1215 b.Run("lxt-obj", func(b *testing.B) { 1216 b.ReportAllocs() 1217 for i := 0; i < b.N; i++ { 1218 err := lxt.UnmarshalString(str, &d) 1219 if err != nil { 1220 b.Fatalf("[%d]:%v", i, err) 1221 } 1222 } 1223 b.StopTimer() 1224 b.SetBytes(int64(b.N)) 1225 }) 1226 // return 1227 b.Run("sonic-obj", func(b *testing.B) { 1228 b.ReportAllocs() 1229 for i := 0; i < b.N; i++ { 1230 err := sonic.UnmarshalString(str, &d) 1231 if err != nil { 1232 b.Fatalf("[%d]:%v", i, err) 1233 } 1234 } 1235 b.StopTimer() 1236 b.SetBytes(int64(b.N)) 1237 }) 1238 }