github.com/lxt1045/json@v0.0.0-20231013032136-54d6b1d6e525/struct_bench_test.go (about) 1 package json 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "math/rand" 8 "reflect" 9 "runtime" 10 "strings" 11 "testing" 12 "unsafe" 13 14 "github.com/bytedance/sonic" 15 "github.com/lxt1045/json/testdata" 16 ) 17 18 func Tt(value reflect.Value) { 19 if value.Kind() != reflect.Ptr { 20 panic("ss") 21 } 22 value = value.Elem() 23 if value.Kind() != reflect.Struct { 24 panic("ss") 25 } 26 field := value.FieldByName("SS") 27 if !field.CanSet() { 28 return 29 } 30 // str := "888" 31 // field.Set(reflect.ValueOf(&str)) 32 field = field.Elem() 33 if !field.CanSet() { 34 return 35 } 36 field.SetString("999") 37 // field.SetIterValue() 38 39 m := value.FieldByName("M") 40 if !m.CanSet() { 41 panic("m") 42 } 43 iter := m.MapRange() 44 if iter == nil { 45 return 46 } 47 for iter.Next() { 48 v := iter.Value().String() 49 v += "-xxx" 50 m.SetMapIndex(iter.Key(), reflect.ValueOf(v)) 51 } 52 } 53 54 func Test_String(t *testing.T) { 55 56 runtime.GC() 57 s := struct { 58 SS *string 59 M map[string]string 60 }{} 61 x := "" 62 s.SS = &x 63 s.M = map[string]string{ 64 "a": "b", 65 "a1": "b11", 66 } 67 t.Run("1", func(t *testing.T) { 68 Tt(reflect.ValueOf(&s)) 69 t.Logf("%+v", s) 70 t.Logf("%+v", *s.SS) 71 }) 72 } 73 74 func Test_parseStr(t *testing.T) { 75 t.Run("map", func(t *testing.T) { 76 src := `"<a href=\"//itunes.apple.com/us/app/twitter/id409789998?mt=12%5C%22\" rel=\"\\\"nofollow\\\"\">Twitter for Mac</a>"` 77 raw, i, n := parseStr(src, -1) 78 t.Logf("%s, i:%d, n:%d", string(raw), i, n) 79 }) 80 } 81 82 // TODO: 83 // 1. SIMD 加速 84 // 5. 全部 key 找出来之后,再排序,再从 bytes 中找出对应的 key? 85 // 11. bytes.IndexByte 和 map 文章 86 87 /* 88 go test -benchmem -run=^$ -bench ^BenchmarkMyUnmarshalPoniter$ github.com/lxt1045/json -count=1 -v -cpuprofile cpu.prof -c 89 go test -benchmem -run=^$ -bench ^BenchmarkMyUnmarshalPoniter$ github.com/lxt1045/json -count=1 -v -memprofile cpu.prof -c 90 go tool pprof ./json.test cpu.prof 91 */ 92 func BenchmarkMyUnmarshalPoniter(b *testing.B) { 93 type Name struct { 94 ZHCN *string `json:"ZH_CN"` 95 ZHCN1 *string `json:"ZH_CN1"` 96 ZHCN2 *string `json:"xx"` 97 ZHCN3 *string `json:"yy"` 98 ZHCN4 *string `json:"DD"` 99 ZHCN5 *string `json:"os"` 100 ZHCN6 *string `json:"test"` 101 ZHCN7 *string `json:"zxzv"` 102 ZHCN8 *string `json:"XDS1"` 103 ENUS *string `json:"EN_US"` 104 } 105 type NameA struct { 106 ZHCN string `json:"ZH_CN"` 107 ZHCN1 string `json:"ZH_CN1"` 108 ZHCN2 string `json:"xx"` 109 ZHCN3 string `json:"yy"` 110 ZHCN4 string `json:"DD"` 111 ZHCN5 string `json:"os"` 112 ZHCN6 string `json:"test"` 113 ZHCN7 string `json:"zxzv"` 114 ZHCN8 string `json:"XDS1"` 115 ENUS string `json:"EN_US"` 116 } 117 bs := []byte(`{ 118 "ZH_CN":"chinesechinesec", 119 "ZH_CN1":"chinesechinesec", 120 "xx":"chinesechinesec", 121 "yy":"chinesechinesec", 122 "DD":"chinesechinesec", 123 "os":"chinesechinesec", 124 "test":"chinesechinesec", 125 "zxzv":"chinesechinesec", 126 "XDS1":"chinesechinesec", 127 "EN_US":"English" 128 }`) 129 str := string(bs) 130 131 d := Name{} 132 err := Unmarshal(bs, &d) 133 if err != nil { 134 b.Fatal(err) 135 } 136 runtime.GC() 137 sonic.UnmarshalString(str, &d) 138 Unmarshal(bs, &d) 139 140 // 141 142 // return 143 b.Run("Unmarshal-p", func(b *testing.B) { 144 d := Name{} 145 b.ReportAllocs() 146 b.ResetTimer() 147 for i := 0; i < b.N; i++ { 148 err := Unmarshal(bs, &d) 149 if err != nil { 150 b.Fatalf("[%d]:%v", i, err) 151 } 152 } 153 b.StopTimer() 154 b.SetBytes(int64(b.N)) 155 }) 156 // return 157 b.Run("sonic-p", func(b *testing.B) { 158 d := Name{} 159 b.ReportAllocs() 160 b.ResetTimer() 161 for i := 0; i < b.N; i++ { 162 err := sonic.UnmarshalString(str, &d) 163 if err != nil { 164 b.Fatalf("[%d]:%v", i, err) 165 } 166 } 167 b.StopTimer() 168 b.SetBytes(int64(b.N)) 169 }) 170 // return 171 b.Run("Unmarshal", func(b *testing.B) { 172 d := NameA{} 173 b.ReportAllocs() 174 b.ResetTimer() 175 for i := 0; i < b.N; i++ { 176 err := Unmarshal(bs, &d) 177 if err != nil { 178 b.Fatalf("[%d]:%v", i, err) 179 } 180 } 181 b.StopTimer() 182 b.SetBytes(int64(b.N)) 183 }) 184 // return 185 b.Run("sonic", func(b *testing.B) { 186 d := NameA{} 187 b.ReportAllocs() 188 b.ResetTimer() 189 for i := 0; i < b.N; i++ { 190 err := sonic.UnmarshalString(str, &d) 191 if err != nil { 192 b.Fatalf("[%d]:%v", i, err) 193 } 194 } 195 b.StopTimer() 196 b.SetBytes(int64(b.N)) 197 }) 198 b.Run("Marshal-p", func(b *testing.B) { 199 b.ReportAllocs() 200 b.ResetTimer() 201 for i := 0; i < b.N; i++ { 202 _, err := Marshal(&d) 203 if err != nil { 204 b.Fatalf("[%d]:%v", i, err) 205 } 206 } 207 b.StopTimer() 208 b.SetBytes(int64(b.N)) 209 }) 210 b.Run("sonic.Marshal-p", func(b *testing.B) { 211 b.ReportAllocs() 212 b.ResetTimer() 213 for i := 0; i < b.N; i++ { 214 _, err := sonic.Marshal(&d) 215 if err != nil { 216 b.Fatalf("[%d]:%v", i, err) 217 } 218 } 219 b.StopTimer() 220 b.SetBytes(int64(b.N)) 221 }) 222 b.Run("sonic.Marshal-p-string", func(b *testing.B) { 223 b.ReportAllocs() 224 b.ResetTimer() 225 for i := 0; i < b.N; i++ { 226 _, err := sonic.MarshalString(&d) 227 if err != nil { 228 b.Fatalf("[%d]:%v", i, err) 229 } 230 } 231 b.StopTimer() 232 b.SetBytes(int64(b.N)) 233 }) 234 } 235 236 func BenchmarkMyUnmarshal(b *testing.B) { 237 name := "Unmarshal" 238 bs := []byte(j0) 239 d := J0{} 240 err := Unmarshal(bs, &d) 241 if err != nil { 242 panic(err) 243 } 244 b.Run(name, func(b *testing.B) { 245 b.ReportAllocs() 246 for i := 0; i < b.N; i++ { 247 err := Unmarshal(bs, &d) 248 if err != nil { 249 b.Fatalf("[%d]:%v", i, err) 250 } 251 } 252 b.StopTimer() 253 b.SetBytes(int64(b.N)) 254 }) 255 } 256 257 func BenchmarkMyUnmarshal2(b *testing.B) { 258 bs := []byte(j0) 259 d := J0{} 260 { 261 err := Unmarshal(bs, &d) 262 if err != nil { 263 b.Fatal(err) 264 } 265 } 266 267 name := "Unmarshal" 268 b.Run(name, func(b *testing.B) { 269 d := map[string]interface{}{} 270 b.ReportAllocs() 271 b.ResetTimer() 272 for i := 0; i < b.N; i++ { 273 err := UnmarshalString(j0, &d) 274 if err != nil { 275 b.Fatal(err) 276 } 277 } 278 b.StopTimer() 279 b.SetBytes(int64(b.N)) 280 }) 281 b.Run(name, func(b *testing.B) { 282 d := map[string]interface{}{} 283 b.ReportAllocs() 284 b.ResetTimer() 285 for i := 0; i < b.N; i++ { 286 err := sonic.UnmarshalString(j0, &d) 287 if err != nil { 288 b.Fatal(err) 289 } 290 } 291 b.StopTimer() 292 b.SetBytes(int64(b.N)) 293 }) 294 } 295 296 // sonic 297 func BenchmarkMyUnmarshal3(b *testing.B) { 298 name := "Unmarshal" 299 bs := []byte(j0) 300 d := J0{} 301 err := Unmarshal(bs, &d) 302 if err != nil { 303 panic(err) 304 } 305 b.Run(name, func(b *testing.B) { 306 b.ReportAllocs() 307 for i := 0; i < b.N; i++ { 308 err := sonic.UnmarshalString(j0, &d) 309 if err != nil { 310 b.Fatalf("[%d]:%v", i, err) 311 } 312 } 313 b.StopTimer() 314 b.SetBytes(int64(b.N)) 315 }) 316 b.Run(name, func(b *testing.B) { 317 b.ReportAllocs() 318 for i := 0; i < b.N; i++ { 319 err := UnmarshalString(j0, &d) 320 if err != nil { 321 b.Fatalf("[%d]:%v", i, err) 322 } 323 } 324 b.StopTimer() 325 b.SetBytes(int64(b.N)) 326 }) 327 } 328 329 /* 330 go test -benchmem -run=^$ -benchtime=10000000x -bench ^BenchmarkUnmarshalStruct$ github.com/lxt1045/json -count=1 -v -cpuprofile cpu.prof -c 331 332 go test -benchmem -run=^$ -v -benchtime=10000000x -bench ^BenchmarkUnmarshalStruct$ github.com/lxt1045/json -count=1 333 BenchmarkUnMarshalStruct/lxt-st-12 10000000 129.2 ns/op 77375851.24 MB/s 0 B/op 0 allocs/op 334 BenchmarkUnMarshalStruct/sonic-st-12 10000000 155.8 ns/op 64166301.93 MB/s 0 B/op 0 allocs/op 335 BenchmarkUnMarshalStruct/lxt-st#01-12 10000000 127.5 ns/op 78409245.03 MB/s 0 B/op 0 allocs/op 336 BenchmarkUnMarshalStruct/sonic-st#01-12 10000000 148.5 ns/op 67361422.86 MB/s 0 B/op 0 allocs/op 337 338 BenchmarkUnmarshalStruct 339 BenchmarkUnmarshalStruct/lxt-st 340 BenchmarkUnmarshalStruct/lxt-st-12 10000000 137.1 ns/op 72926417.64 MB/s 0 B/op 0 allocs/op 341 BenchmarkUnmarshalStruct/sonic-st 342 BenchmarkUnmarshalStruct/sonic-st-12 10000000 156.1 ns/op 64064282.98 MB/s 0 B/op 0 allocs/op 343 BenchmarkUnmarshalStruct/lxt-st-string 344 BenchmarkUnmarshalStruct/lxt-st-string-12 10000000 137.0 ns/op 72995122.89 MB/s 0 B/op 0 allocs/op 345 BenchmarkUnmarshalStruct/lxt-st#01 346 BenchmarkUnmarshalStruct/lxt-st#01-12 10000000 137.7 ns/op 72632868.70 MB/s 0 B/op 0 allocs/op 347 BenchmarkUnmarshalStruct/sonic-st#01 348 BenchmarkUnmarshalStruct/sonic-st#01-12 10000000 153.9 ns/op 64996997.62 MB/s 0 B/op 0 allocs/op 349 BenchmarkUnmarshalStruct/lxt.marshal-st 350 BenchmarkUnmarshalStruct/lxt.marshal-st-12 10000000 77.56 ns/op 128934363.78 MB/s 56 B/op 0 allocs/op 351 BenchmarkUnmarshalStruct/sonic.marshal-st 352 BenchmarkUnmarshalStruct/sonic.marshal-st-12 10000000 193.1 ns/op 51773914.52 MB/s 133 B/op 4 allocs/op 353 */ 354 func BenchmarkUnmarshalStruct(b *testing.B) { 355 type Name struct { 356 ZHCN string `json:"ZH_CN"` 357 ENUS string `json:"EN_US"` 358 Count int `json:"count"` 359 } 360 bs := []byte(`{ 361 "ZH_CN":"chinesechinesec", 362 "EN_US":"English", 363 "count":8 364 }`) 365 str := string(bs) 366 var d Name 367 Unmarshal(bs, &d) 368 sonic.UnmarshalString(str, &d) 369 370 runs := []struct { 371 name string 372 f func() 373 }{ 374 {"lxt-st", 375 func() { 376 Unmarshal(bs, &d) 377 }, 378 }, 379 { 380 "sonic-st", 381 func() { 382 sonic.UnmarshalString(str, &d) 383 }, 384 }, 385 {"lxt-st-string", 386 func() { 387 UnmarshalString(str, &d) 388 }, 389 }, 390 { 391 "sonic-st", 392 func() { 393 sonic.UnmarshalString(str, &d) 394 }, 395 }, 396 {"lxt.marshal-st", 397 func() { 398 Marshal(&d) 399 }, 400 }, 401 { 402 "sonic.marshal-st", 403 func() { 404 sonic.Marshal(&d) 405 }, 406 }, 407 } 408 409 // b.RunParallel(func(pb *testing.PB) { 410 // for pb.Next() { 411 // Unmarshal(bs, &d) 412 // } 413 // }) 414 // b.RunParallel(func(pb *testing.PB) { 415 // for pb.Next() { 416 // sonic.UnmarshalString(str, &d) 417 // } 418 // }) 419 // return 420 for _, r := range runs[:] { 421 runtime.GC() 422 b.Run(r.name, func(b *testing.B) { 423 b.ReportAllocs() 424 for i := 0; i < b.N; i++ { 425 r.f() 426 } 427 b.SetBytes(int64(b.N)) 428 b.StopTimer() 429 }) 430 } 431 } 432 433 /* 434 go test -benchmem -run=^$ -bench ^BenchmarkUnMarshalStructMap$ github.com/lxt1045/json -count=1 -v -cpuprofile cpu.prof -c 435 go test -benchmem -run=^$ -bench ^BenchmarkUnMarshalStructMap$ github.com/lxt1045/json -count=1 -v -memprofile cpu.prof -c 436 go tool pprof ./json.test cpu.prof 437 // 438 */ 439 func BenchmarkUnMarshalStructMap(b *testing.B) { 440 bs := []byte(`{ 441 "ZH_CN1":"chinesechinese", 442 "xx":"chinese", 443 "yy":"chinese", 444 "os":"chinesechinese", 445 "test":"chinesechinese", 446 "zxzv":"chinesechinese", 447 "ZH_CN":"chinese", 448 "EN_US":"English", 449 "XDS1":"English" 450 }`) 451 type Name struct { 452 ZHCN *string `json:"ZH_CN"` 453 ZHCN1 *string `json:"ZH_CN1"` 454 ZHCN2 *string `json:"xx"` 455 ZHCN3 *string `json:"yy"` 456 ZHCN5 *string `json:"os"` 457 ZHCN6 *string `json:"test"` 458 ZHCN7 *string `json:"zxzv"` 459 ZHCN8 *string `json:"XDS1"` 460 ENUS *string `json:"EN_US"` 461 } 462 st := Name{} 463 str := string(bs) 464 var d map[string]interface{} 465 err := Unmarshal(bs, &d) 466 if err != nil { 467 b.Fatal(err) 468 } 469 err = sonic.UnmarshalString(str, &d) 470 if err != nil { 471 b.Fatal(err) 472 } 473 runs := []struct { 474 name string 475 f func() 476 }{ 477 {"lxt-map", 478 func() { 479 err := Unmarshal(bs, &d) 480 if err != nil { 481 b.Fatal(err) 482 } 483 }, 484 }, 485 { 486 "sonic-map", 487 func() { 488 err := sonic.UnmarshalString(str, &d) 489 if err != nil { 490 b.Fatal(err) 491 } 492 }, 493 }, 494 {"lxt-map", 495 func() { 496 err := Unmarshal(bs, &d) 497 if err != nil { 498 b.Fatal(err) 499 } 500 }, 501 }, 502 { 503 "sonic-map", 504 func() { 505 err := sonic.UnmarshalString(str, &d) 506 if err != nil { 507 b.Fatal(err) 508 } 509 }, 510 }, 511 {"lxt-st", 512 func() { 513 err := Unmarshal(bs, &st) 514 if err != nil { 515 b.Fatal(err) 516 } 517 }, 518 }, 519 } 520 521 for _, r := range runs[:] { 522 b.Run(r.name, func(b *testing.B) { 523 b.ReportAllocs() 524 for i := 0; i < b.N; i++ { 525 r.f() 526 } 527 b.SetBytes(int64(b.N)) 528 b.StopTimer() 529 }) 530 } 531 } 532 533 /* 534 go test -benchmem -run=^$ -benchtime=1000000x -bench ^BenchmarkUnmarshalStruct1x$ github.com/lxt1045/json -count=1 -v -cpuprofile cpu.prof -c 535 go test -benchmem -run=^$ -bench ^BenchmarkUnmarshalStruct1x$ github.com/lxt1045/json -count=1 -v -memprofile cpu.prof -c 536 go tool pprof ./json.test cpu.prof 537 go test -benchmem -run=^$ -benchtime=10000000x -bench "^BenchmarkUnmarshalStruct1x$" 538 BenchmarkUnmarshalStruct1x/lxt-st-12 1000000 1221 ns/op 320 B/op 1 allocs/op 539 BenchmarkUnmarshalStruct1x/sonic-st-12 1000000 1571 ns/op 364 B/op 1 allocs/op 540 BenchmarkUnmarshalStruct1x/lxt-st#01-12 1000000 1202 ns/op 320 B/op 1 allocs/op 541 BenchmarkUnmarshalStruct1x/sonic-st#01-12 1000000 1569 ns/op 364 B/op 1 allocs/op 542 543 BenchmarkUnmarshalStruct1x/lxt-st-12 1000000 1161 ns/op 320 B/op 1 allocs/op 544 BenchmarkUnmarshalStruct1x/sonic-st-12 1000000 1593 ns/op 365 B/op 1 allocs/op 545 BenchmarkUnmarshalStruct1x/lxt-st#01-12 1000000 1171 ns/op 320 B/op 1 allocs/op 546 BenchmarkUnmarshalStruct1x/sonic-st#01-12 1000000 1554 ns/op 359 B/op 1 allocs/op 547 */ 548 func BenchmarkUnmarshalStruct1x(b *testing.B) { 549 bs := []byte(j0) 550 data := string(bs) 551 d := J0{} 552 err := Unmarshal(bs, &d) 553 if err != nil { 554 b.Fatal(err) 555 } 556 _, err = json.Marshal(&d) 557 if err != nil { 558 b.Fatal(err) 559 } 560 561 runtime.GC() 562 m := J0{} 563 b.Run("lxt-Unmarshal", func(b *testing.B) { 564 for i := 0; i < b.N; i++ { 565 err := UnmarshalString(data, &m) 566 if err != nil { 567 panic(err) 568 } 569 } 570 }) 571 // return 572 runtime.GC() 573 b.Run("lxt-Unmarshal", func(b *testing.B) { 574 for i := 0; i < b.N; i++ { 575 err := sonic.UnmarshalString(data, &m) 576 if err != nil { 577 panic(err) 578 } 579 } 580 }) 581 // return 582 runtime.GC() 583 _ = fmt.Sprintf("d :%+v", d) 584 runs := []struct { 585 name string 586 f func() 587 }{ 588 {"lxt-st", 589 func() { 590 m := J0{} 591 err := Unmarshal(bs, &m) 592 if err != nil { 593 panic(err) 594 } 595 }, 596 }, 597 { 598 "sonic-st", 599 func() { 600 m := J0{} 601 err := sonic.UnmarshalString(data, &m) 602 if err != nil { 603 panic(err) 604 } 605 }, 606 }, 607 {"lxt-st", 608 func() { 609 m := J0{} 610 err := Unmarshal(bs, &m) 611 if err != nil { 612 panic(err) 613 } 614 }, 615 }, 616 { 617 "sonic-st", 618 func() { 619 m := J0{} 620 err := sonic.UnmarshalString(data, &m) 621 if err != nil { 622 panic(err) 623 } 624 }, 625 }, 626 } 627 628 for _, r := range runs[:] { 629 runtime.GC() 630 b.Run(r.name, func(b *testing.B) { 631 for i := 0; i < b.N; i++ { 632 r.f() 633 } 634 }) 635 } 636 } 637 638 /* 639 go test -benchmem -run=^$ -bench ^BenchmarkUnmarshalStruct1xMap$ github.com/lxt1045/json -count=1 -v -cpuprofile cpu.prof -c 640 go test -benchmem -run=^$ -bench ^BenchmarkUnmarshalStruct1xMap$ github.com/lxt1045/json -count=1 -v -memprofile cpu.prof -c 641 go tool pprof ./json.test cpu.prof 642 // */ 643 644 func BenchmarkUnmarshalStruct1xMap(b *testing.B) { 645 bs := []byte(j0) 646 data := string(bs) 647 d := J0{} 648 err := Unmarshal(bs, &d) 649 if err != nil { 650 b.Fatal(err) 651 } 652 _, err = json.Marshal(&d) 653 if err != nil { 654 b.Fatal(err) 655 } 656 runs := []struct { 657 name string 658 f func() 659 }{ 660 {"lxt-map", 661 func() { 662 m := map[string]interface{}{} 663 err := Unmarshal(bs, &m) 664 if err != nil { 665 b.Fatal(err) 666 } 667 }, 668 }, 669 { 670 "sonic-map", 671 func() { 672 m := map[string]interface{}{} 673 err := sonic.UnmarshalString(data, &m) 674 if err != nil { 675 b.Fatal(err) 676 } 677 }, 678 }, 679 {"lxt-map", 680 func() { 681 m := map[string]interface{}{} 682 err := Unmarshal(bs, &m) 683 if err != nil { 684 b.Fatal(err) 685 } 686 }, 687 }, 688 { 689 "sonic-map", 690 func() { 691 m := map[string]interface{}{} 692 err := sonic.UnmarshalString(data, &m) 693 if err != nil { 694 b.Fatal(err) 695 } 696 }, 697 }, 698 {"lxt-st", 699 func() { 700 m := J0{} 701 err := Unmarshal(bs, &m) 702 if err != nil { 703 b.Fatal(err) 704 } 705 }, 706 }, 707 { 708 "sonic-st", 709 func() { 710 m := J0{} 711 err := sonic.UnmarshalString(data, &m) 712 if err != nil { 713 b.Fatal(err) 714 } 715 }, 716 }, 717 } 718 719 for _, r := range runs[:] { 720 b.Run(r.name, func(b *testing.B) { 721 for i := 0; i < b.N; i++ { 722 r.f() 723 } 724 }) 725 } 726 } 727 728 /* 729 go test -benchmem -run=^$ -bench ^BenchmarkUnmarshalStruct1x_medium $ github.com/lxt1045/json -count=1 -v -cpuprofile cpu.prof -c 730 */ 731 func BenchmarkUnmarshalStruct1x_small(b *testing.B) { 732 bs := []byte(testdata.BookData) 733 data := string(bs) 734 d := testdata.Book{} 735 err := Unmarshal(bs, &d) 736 if err != nil { 737 b.Fatal(err) 738 } 739 bsOut, err := json.Marshal(&d) 740 if err != nil { 741 b.Fatal(err) 742 } 743 m := testdata.Book{} 744 sonic.UnmarshalString(data, &m) 745 runtime.GC() 746 _ = fmt.Sprintf("d :%+v", d) 747 if string(bsOut) != string(testdata.BookDataOut) { 748 str := string(bsOut) 749 str2 := string(testdata.BookDataOut) 750 for i := range str2 { 751 if len(str) > i && str[i] != str2[i] { 752 l := len(str2) 753 if l-i > 8 { 754 l = i + 8 755 } 756 if len(str) >= len(str2) { 757 b.Logf("i:%d, c:%s,%s", i, str[i:l], str2[i:l]) 758 } 759 } 760 } 761 b.Fatalf("len:%d,%d,bsOut:%s", len(str), len(str2), str) 762 } 763 runs := []struct { 764 name string 765 f func() 766 }{ 767 {"lxt-st", 768 func() { 769 // m := testdata.Book{} 770 err := Unmarshal(bs, &m) 771 if err != nil { 772 panic(err) 773 } 774 }, 775 }, 776 { 777 "sonic-st", 778 func() { 779 // m := testdata.Book{} 780 err := sonic.UnmarshalString(data, &m) 781 if err != nil { 782 panic(err) 783 } 784 }, 785 }, 786 {"lxt-st", 787 func() { 788 // m := testdata.Book{} 789 err := Unmarshal(bs, &m) 790 if err != nil { 791 panic(err) 792 } 793 }, 794 }, 795 { 796 "sonic-st", 797 func() { 798 // m := testdata.Book{} 799 err := sonic.UnmarshalString(data, &m) 800 if err != nil { 801 panic(err) 802 } 803 }, 804 }, 805 {"std-st", 806 func() { 807 // m := testdata.Book{} 808 err := json.Unmarshal(bs, &m) 809 if err != nil { 810 panic(err) 811 } 812 }, 813 }, 814 { 815 "sonic.marshal-st", 816 func() { 817 _, err := sonic.Marshal(&m) 818 if err != nil { 819 panic(err) 820 } 821 }, 822 }, 823 { 824 "lxt.marshal-st", 825 func() { 826 _, err := Marshal(&m) 827 if err != nil { 828 panic(err) 829 } 830 }, 831 }, 832 {"std.marshal-st", 833 func() { 834 _, err := json.Marshal(&m) 835 if err != nil { 836 panic(err) 837 } 838 }, 839 }, 840 } 841 842 if false { 843 runtime.GC() 844 b.Run("RunParallel-lxt", func(b *testing.B) { 845 b.SetBytes(int64(len(data))) 846 b.ResetTimer() 847 b.RunParallel(func(pb *testing.PB) { 848 for pb.Next() { 849 UnmarshalString(data, &m) 850 } 851 }) 852 }) 853 runtime.GC() 854 b.Run("RunParallel-sonic", func(b *testing.B) { 855 b.SetBytes(int64(len(data))) 856 b.ResetTimer() 857 b.RunParallel(func(pb *testing.PB) { 858 for pb.Next() { 859 sonic.UnmarshalString(data, &m) 860 } 861 }) 862 }) 863 } 864 865 for _, r := range runs[:] { 866 runtime.GC() 867 b.Run(r.name, func(b *testing.B) { 868 b.ReportAllocs() 869 b.SetBytes(int64(len(data))) 870 b.ResetTimer() 871 for i := 0; i < b.N; i++ { 872 r.f() 873 } 874 }) 875 } 876 } 877 878 func BenchmarkUnmarshalStruct1x_medium(b *testing.B) { 879 bs := []byte(testdata.TwitterJson) 880 data := string(bs) 881 d := testdata.TwitterStruct{} 882 err := Unmarshal(bs, &d) 883 if err != nil { 884 b.Fatal(err) 885 } 886 m := testdata.TwitterStruct{} 887 err = sonic.UnmarshalString(data, &m) 888 if err != nil { 889 b.Fatal(err) 890 } 891 runtime.GC() 892 _ = fmt.Sprintf("d :%+v", d) 893 894 bsOut, err := json.Marshal(&d) 895 if err != nil { 896 b.Fatal(err) 897 } 898 if string(bsOut) != testdata.TwitterJsonOut { 899 str := string(bsOut) 900 for i := range testdata.TwitterJsonOut { 901 if len(str) > i+8 && str[i] != testdata.TwitterJsonOut[i] { 902 b.Logf("i:%d, c:%s,%s", i, str[i:i+8], testdata.TwitterJsonOut[i:i+8]) 903 } 904 } 905 b.Fatalf("len:%d,%d,bsOut:%s", len(str), len(testdata.TwitterJsonOut), str) 906 } 907 runs := []struct { 908 name string 909 f func() 910 }{ 911 {"lxt-st", 912 func() { 913 // m := testdata.TwitterStruct{} 914 err := Unmarshal(bs, &m) 915 if err != nil { 916 panic(err) 917 } 918 }, 919 }, 920 { 921 "sonic-st", 922 func() { 923 // m := testdata.TwitterStruct{} 924 err := sonic.UnmarshalString(data, &m) 925 if err != nil { 926 panic(err) 927 } 928 }, 929 }, 930 {"lxt-st", 931 func() { 932 // m := testdata.TwitterStruct{} 933 err := Unmarshal(bs, &m) 934 if err != nil { 935 panic(err) 936 } 937 }, 938 }, 939 { 940 "sonic-st", 941 func() { 942 // m := testdata.TwitterStruct{} 943 err := sonic.UnmarshalString(data, &m) 944 if err != nil { 945 panic(err) 946 } 947 }, 948 }, 949 {"std-st", 950 func() { 951 // m := testdata.Book{} 952 err := json.Unmarshal(bs, &m) 953 if err != nil { 954 panic(err) 955 } 956 }, 957 }, 958 { 959 "sonic.marshal-st", 960 func() { 961 _, err := sonic.Marshal(&m) 962 if err != nil { 963 panic(err) 964 } 965 }, 966 }, 967 { 968 "lxt.marshal-st", 969 func() { 970 _, err := Marshal(&m) 971 if err != nil { 972 panic(err) 973 } 974 }, 975 }, 976 {"std.marshal-st", 977 func() { 978 _, err := json.Marshal(&m) 979 if err != nil { 980 panic(err) 981 } 982 }, 983 }, 984 } 985 986 for _, r := range runs[:] { 987 runtime.GC() 988 b.Run(r.name, func(b *testing.B) { 989 b.ReportAllocs() 990 b.SetBytes(int64(len(bs))) 991 b.ResetTimer() 992 for i := 0; i < b.N; i++ { 993 r.f() 994 } 995 }) 996 } 997 } 998 999 func BenchmarkUnmarshalStruct1x_large(b *testing.B) { 1000 bs := []byte(testdata.TwitterJsonLarge) 1001 data := string(bs) 1002 d := testdata.TwitterStruct{} 1003 d2 := testdata.TwitterStruct{} 1004 err := json.Unmarshal(bs, &d2) 1005 if err != nil { 1006 b.Fatal(err) 1007 } 1008 1009 m := testdata.TwitterStruct{} 1010 err = sonic.UnmarshalString(data, &m) 1011 if err != nil { 1012 panic(err) 1013 } 1014 1015 // return 1016 err = Unmarshal(bs, &d) 1017 if err != nil { 1018 b.Fatal(err) 1019 } 1020 runtime.GC() 1021 _ = fmt.Sprintf("d :%+v", d) 1022 1023 // bsOut, err := json.Marshal(&d) 1024 // if err != nil { 1025 // b.Fatal(err) 1026 // } 1027 // _ = bsOut 1028 // dGlobal = fmt.Sprintf("bsOut:%s", string(bsOut)) 1029 // if string(bsOut) != testdata.TwitterJsonOut { 1030 // str := string(bsOut) 1031 // b.Fatalf("len:%d,%d,bsOut:%s", len(str), len(testdata.TwitterJsonOut), str) 1032 // for i := range str { 1033 // if str[i] != testdata.TwitterJsonOut[i] { 1034 // b.Logf("i:%d, c:%s,%s", i, str[i:i+8], testdata.TwitterJsonOut[i:i+8]) 1035 // } 1036 // } 1037 // } 1038 runs := []struct { 1039 name string 1040 f func() 1041 }{ 1042 {"lxt-st", 1043 func() { 1044 // m := testdata.TwitterStruct{} 1045 err := Unmarshal(bs, &m) 1046 if err != nil { 1047 panic(err) 1048 } 1049 }, 1050 }, 1051 { 1052 "sonic-st", 1053 func() { 1054 // m := testdata.TwitterStruct{} 1055 err := sonic.UnmarshalString(data, &m) 1056 if err != nil { 1057 panic(err) 1058 } 1059 }, 1060 }, 1061 {"lxt-st", 1062 func() { 1063 // m := testdata.TwitterStruct{} 1064 err := Unmarshal(bs, &m) 1065 if err != nil { 1066 panic(err) 1067 } 1068 }, 1069 }, 1070 { 1071 "sonic-st", 1072 func() { 1073 // m := testdata.TwitterStruct{} 1074 err := sonic.UnmarshalString(data, &m) 1075 if err != nil { 1076 panic(err) 1077 } 1078 }, 1079 }, 1080 {"std-st", 1081 func() { 1082 // m := testdata.TwitterStruct{} 1083 err := json.Unmarshal(bs, &m) 1084 if err != nil { 1085 panic(err) 1086 } 1087 }, 1088 }, 1089 { 1090 "sonic.marshal-st", 1091 func() { 1092 _, err := sonic.Marshal(&m) 1093 if err != nil { 1094 panic(err) 1095 } 1096 }, 1097 }, 1098 { 1099 "lxt.marshal-st", 1100 func() { 1101 _, err := Marshal(&m) 1102 if err != nil { 1103 panic(err) 1104 } 1105 }, 1106 }, 1107 {"std.marshal-st", 1108 func() { 1109 _, err := json.Marshal(&m) 1110 if err != nil { 1111 panic(err) 1112 } 1113 }, 1114 }, 1115 } 1116 1117 for _, r := range runs { 1118 runtime.GC() 1119 b.Run(r.name, func(b *testing.B) { 1120 b.ReportAllocs() 1121 b.SetBytes(int64(len(bs))) 1122 b.ResetTimer() 1123 for i := 0; i < b.N; i++ { 1124 r.f() 1125 } 1126 }) 1127 } 1128 } 1129 1130 /* 1131 go test -benchmem -run=^$ -bench ^BenchmarkMyUnmarshalLarge$ github.com/lxt1045/json -count=1 -v -cpuprofile cpu.prof -c 1132 go test -benchmem -run=^$ -bench ^BenchmarkMyUnmarshalLarge$ github.com/lxt1045/json -count=1 -v -memprofile cpu.prof -c 1133 go tool pprof ./json.test cpu.prof 1134 // 1135 */ 1136 func BenchmarkMyUnmarshalLarge(b *testing.B) { 1137 bs := []byte(testdata.TwitterJson) 1138 bs = []byte(testdata.TwitterJsonLarge) 1139 data := string(bs) 1140 _ = data 1141 d := testdata.TwitterStruct{} 1142 // return 1143 err := Unmarshal(bs, &d) 1144 if err != nil { 1145 b.Fatal(err) 1146 } 1147 b.Run("large", func(b *testing.B) { 1148 b.ReportAllocs() 1149 for i := 0; i < b.N; i++ { 1150 d := testdata.TwitterStruct{} 1151 // err := json.Unmarshal(bs, &d) 1152 // if err != nil { 1153 // b.Fatalf("[%d]:%v", i, err) 1154 // } 1155 err := Unmarshal(bs, &d) 1156 if err != nil { 1157 b.Fatalf("[%d]:%v", i, err) 1158 } 1159 // err := sonic.UnmarshalString(data, &m) 1160 // if err != nil { 1161 // panic(err) 1162 // } 1163 } 1164 b.StopTimer() 1165 b.SetBytes(int64(b.N)) 1166 }) 1167 return 1168 b.Run("spaceTable", func(b *testing.B) { 1169 b.ReportAllocs() 1170 for i := 0; i < b.N; i++ { 1171 for i := 0; i < len(bs); i++ { 1172 if spaceTable[bs[i]] { 1173 b0 = bs[i] 1174 } 1175 } 1176 } 1177 b.StopTimer() 1178 b.SetBytes(int64(b.N)) 1179 }) 1180 } 1181 1182 /* 1183 go test -benchmem -run=^$ -bench ^BenchmarkMyUnmarshalSmall$ github.com/lxt1045/json -count=1 -v -cpuprofile cpu.prof -c 1184 go test -benchmem -run=^$ -bench ^BenchmarkMyUnmarshalSmall$ github.com/lxt1045/json -count=1 -v -memprofile cpu.prof -c 1185 go tool pprof ./json.test cpu.prof 1186 // 1187 */ 1188 func BenchmarkMyUnmarshalSmall(b *testing.B) { 1189 bs := []byte(testdata.BookData) 1190 b.Run("small", func(b *testing.B) { 1191 for i := 0; i < b.N; i++ { 1192 m := testdata.Book{} 1193 err := Unmarshal(bs, &m) 1194 if err != nil { 1195 panic(err) 1196 } 1197 } 1198 }) 1199 } 1200 1201 /* 1202 go test -benchmem -run=^$ -bench ^BenchmarkMarshalMedium $ github.com/lxt1045/json -count=1 -v -cpuprofile cpu.prof -c 1203 go test -benchmem -run=^$ -bench ^BenchmarkMarshalLarge$ github.com/lxt1045/json -count=1 -v -memprofile cpu.prof -c 1204 go tool pprof ./json.test cpu.prof 1205 // 1206 */ 1207 func BenchmarkMarshalLarge(b *testing.B) { 1208 bs := []byte(testdata.TwitterJsonLarge) 1209 d := testdata.TwitterStruct{} 1210 err := json.Unmarshal(bs, &d) 1211 if err != nil { 1212 b.Fatal(err) 1213 } 1214 runtime.GC() 1215 b.Run("Large", func(b *testing.B) { 1216 for i := 0; i < b.N; i++ { 1217 _, err := Marshal(&d) 1218 if err != nil { 1219 b.Fatal(err) 1220 } 1221 } 1222 }) 1223 } 1224 func BenchmarkMarshalMedium(b *testing.B) { 1225 bs := []byte(testdata.TwitterJson) 1226 d := testdata.TwitterStruct{} 1227 err := Unmarshal(bs, &d) 1228 if err != nil { 1229 b.Fatal(err) 1230 } 1231 runtime.GC() 1232 b.Run("Medium ", func(b *testing.B) { 1233 for i := 0; i < b.N; i++ { 1234 _, err := Marshal(&d) 1235 if err != nil { 1236 b.Fatal(err) 1237 } 1238 } 1239 }) 1240 } 1241 func BenchmarkMarshalSmall(b *testing.B) { 1242 var vBook = func() testdata.Book { 1243 bs := []byte(testdata.BookData) 1244 m := testdata.Book{} 1245 err := Unmarshal(bs, &m) 1246 if err != nil { 1247 panic(err) 1248 } 1249 return m 1250 }() 1251 b.Run("small", func(b *testing.B) { 1252 for i := 0; i < b.N; i++ { 1253 _, err := Marshal(&vBook) 1254 if err != nil { 1255 b.Fatal(err) 1256 } 1257 } 1258 }) 1259 } 1260 1261 var pp unsafe.Pointer 1262 var pm *map[string]interface{} 1263 var m map[string]interface{} 1264 var str *string 1265 var pbs *[]byte 1266 var bs []byte 1267 var pbool *bool 1268 var b0 byte 1269 var iface *interface{} 1270 1271 func BenchmarkUnmarshalStruct20(b *testing.B) { 1272 bs := []byte(j0) 1273 data := string(bs) 1274 d := J0{} 1275 err := Unmarshal(bs, &d) 1276 if err != nil { 1277 b.Fatal(err) 1278 } 1279 bs, err = json.Marshal(&d) 1280 if err != nil { 1281 b.Fatal(err) 1282 } 1283 runs := []struct { 1284 name string 1285 f func() 1286 }{ 1287 {"std", 1288 func() { 1289 var m map[string]interface{} 1290 json.Unmarshal(bs, &m) 1291 }, 1292 }, 1293 {"std-st", 1294 func() { 1295 m := J0{} 1296 json.Unmarshal(bs, &m) 1297 }, 1298 }, 1299 { 1300 "sonic", 1301 func() { 1302 var m map[string]interface{} 1303 sonic.UnmarshalString(data, &m) 1304 }, 1305 }, 1306 {"lxt-st", 1307 func() { 1308 m := J0{} 1309 Unmarshal(bs, &m) 1310 }, 1311 }, 1312 { 1313 "sonic-st", 1314 func() { 1315 m := J0{} 1316 sonic.UnmarshalString(data, &m) 1317 }, 1318 }, 1319 {"lxt-st", 1320 func() { 1321 m := J0{} 1322 Unmarshal(bs, &m) 1323 }, 1324 }, 1325 { 1326 "sonic-st", 1327 func() { 1328 m := J0{} 1329 sonic.UnmarshalString(data, &m) 1330 }, 1331 }, 1332 } 1333 1334 for _, r := range runs[3:] { 1335 b.Run(r.name, func(b *testing.B) { 1336 b.ReportAllocs() 1337 for i := 0; i < b.N; i++ { 1338 r.f() 1339 } 1340 b.StopTimer() 1341 b.SetBytes(int64(b.N)) 1342 }) 1343 } 1344 } 1345 1346 func Test_tagParse(t *testing.T) { 1347 t.Run("map", func(t *testing.T) { 1348 type BizName struct { 1349 ZHCN string `json:"ZH_CN"` 1350 ENUS string `json:"EN_US"` 1351 } 1352 type DataSt struct { 1353 ItemID []int64 `json:"ItemID,string"` 1354 BizName []BizName `json:"BizName"` 1355 BizCode string `json:"BizCode"` 1356 BizCode1 string 1357 } 1358 d := DataSt{} 1359 typ := reflect.TypeOf(&d) 1360 typ = typ.Elem() 1361 to, err := NewStructTagInfo(typ, nil) 1362 if err != nil { 1363 t.Fatal(err) 1364 } 1365 t.Logf("to:%+v", to) 1366 return 1367 }) 1368 } 1369 1370 func TestMyUnmarshal(t *testing.T) { 1371 d := J0{} 1372 err := Unmarshal([]byte(j0), &d) 1373 if err != nil { 1374 t.Fatalf("%+v", err) 1375 } 1376 1377 bs, err := json.Marshal(d) 1378 if err != nil { 1379 t.Fatal(err) 1380 } 1381 t.Logf("to:%s", string(bs)) 1382 } 1383 1384 var bGlobal = false 1385 1386 func BenchmarkIsSpace(b *testing.B) { 1387 bs := make([]byte, 10240) 1388 for i := range bs { 1389 bs[i] = byte(rand.Uint32()) 1390 } 1391 const charSpace uint32 = 1<<('\t'-1) | 1<<('\n'-1) | 1<<('\v'-1) | 1<<('\f'-1) | 1<<('\r'-1) | 1<<(' '-1) 1392 1393 b.Run("1", func(b *testing.B) { 1394 b.ReportAllocs() 1395 b.ResetTimer() 1396 for i := 0; i < b.N; i++ { 1397 b := bs[i%10240] 1398 bGlobal = b == 0x85 || b == 0xA0 || (charSpace>>(b-1)&0x1 > 0) 1399 } 1400 b.SetBytes(int64(b.N)) 1401 b.StopTimer() 1402 }) 1403 b.Run("2", func(b *testing.B) { 1404 b.ReportAllocs() 1405 b.ResetTimer() 1406 for i := 0; i < b.N; i++ { 1407 b := bs[i%10240] 1408 bGlobal = b == 0x85 || b == 0xA0 || b == '\t' || b == '\n' || b == '\v' || b == '\f' || b == '\r' || b == ' ' 1409 } 1410 b.SetBytes(int64(b.N)) 1411 b.StopTimer() 1412 }) 1413 b.Run("3", func(b *testing.B) { 1414 b.ReportAllocs() 1415 b.ResetTimer() 1416 for i := 0; i < b.N; i++ { 1417 b := bs[i%10240] 1418 switch b { 1419 // toto: 用bitmap加速: 1420 case '\t', '\n', '\v', '\f', '\r', ' ', 0x85, 0xA0: 1421 bGlobal = true 1422 } 1423 bGlobal = false 1424 } 1425 b.SetBytes(int64(b.N)) 1426 b.StopTimer() 1427 }) 1428 b.Run("4", func(b *testing.B) { 1429 table := [256]bool{} 1430 for i := range table { 1431 b := byte(i) 1432 if b == 0x85 || b == 0xA0 || b == '\t' || b == '\n' || b == '\v' || b == '\f' || b == '\r' || b == ' ' { 1433 table[i] = true 1434 } 1435 } 1436 1437 b.ReportAllocs() 1438 b.ResetTimer() 1439 for i := 0; i < b.N; i++ { 1440 b := bs[i%10240] 1441 bGlobal = table[b] 1442 } 1443 b.SetBytes(int64(b.N)) 1444 b.StopTimer() 1445 }) 1446 b.Run("5", func(b *testing.B) { 1447 table := [4]uint64{} 1448 for i := range table { 1449 b := byte(i) 1450 if b == 0x85 || b == 0xA0 || b == '\t' || b == '\n' || b == '\v' || b == '\f' || b == '\r' || b == ' ' { 1451 idx := i / 64 1452 n := i % 64 1453 table[idx] |= 1 << n 1454 } 1455 } 1456 1457 b.ReportAllocs() 1458 b.ResetTimer() 1459 for i := 0; i < b.N; i++ { 1460 b := bs[i%10240] 1461 idx := b / 64 1462 n := b % 64 1463 bGlobal = table[idx]&(1<<n) > 0 1464 } 1465 b.SetBytes(int64(b.N)) 1466 b.StopTimer() 1467 }) 1468 1469 } 1470 1471 func BenchmarkCron(b *testing.B) { 1472 bss := []string{ 1473 ":x", 1474 ": x", 1475 " : x", 1476 " x", 1477 } 1478 var j int 1479 for x, bs := range bss { 1480 ss := fmt.Sprintf("-%d", x) 1481 b.Run("space"+ss, func(b *testing.B) { 1482 b.ResetTimer() 1483 for i := 0; i < b.N; i++ { 1484 j = trimSpace(bs) 1485 if bs[j] != ':' { 1486 b.Fatal("err") 1487 } 1488 j = trimSpace(bs[j+1:]) 1489 } 1490 b.StopTimer() 1491 }) 1492 b.Run("cron"+ss, func(b *testing.B) { 1493 n := 0 1494 b.ResetTimer() 1495 for i := 0; i < b.N; i++ { 1496 j, n = parseByte(bs, ':') 1497 if n != 1 { 1498 b.Fatal("n!=1") 1499 } 1500 _ = j 1501 } 1502 b.StopTimer() 1503 }) 1504 } 1505 } 1506 1507 func TestMyUnmarshalStd(t *testing.T) { 1508 var j = `{ 1509 "BizName": { 1510 "ZH_CN": "职级", 1511 "EN_US": "job-level" 1512 }, 1513 "Description": { 1514 "ZH_CN": "", 1515 "EN_US": "" 1516 } 1517 }` 1518 type I18N struct { 1519 ZH_CN, EN_US string 1520 } 1521 // m := map[string]interface{}{} 1522 m := map[string]I18N{ 1523 "test": { 1524 "1", "2", 1525 }, 1526 } 1527 err := json.Unmarshal([]byte(j), &m) 1528 if err != nil { 1529 t.Fatal(err) 1530 } 1531 t.Logf("%T:%+v", m, m) 1532 } 1533 1534 var bsG string 1535 var bsG1 []byte 1536 1537 func BenchmarkTrimSpace(b *testing.B) { 1538 bs0 := make([]byte, 16+len(j0)) 1539 pbs := (*[1 << 31]byte)(unsafe.Pointer((uintptr(unsafe.Pointer(&bs0[0])) + 0xf) & (^uintptr(0xf)))) 1540 bs := pbs[:len(j0x)] 1541 d := J0{} 1542 json.Unmarshal([]byte(j0), &d) 1543 bs, _ = json.Marshal(&d) 1544 b.Log(string(bs)) 1545 // copy(bs, j0) 1546 countG := [7]int{} 1547 table := [256]bool{'\t': true, '\n': true, '\v': true, '\f': true, '\r': true, ' ': true, 0x85: true, 0xA0: true} 1548 1549 xs1 := "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" 1550 for i := 0; i < 3; i++ { 1551 xs1 += xs1 1552 } 1553 b.Run("bytes.IndexByte", func(b *testing.B) { 1554 b.ReportAllocs() 1555 b.ResetTimer() 1556 for i := 0; i < b.N; i++ { 1557 strings.Index(xs1, "asdfgjlnd") 1558 } 1559 b.SetBytes(int64(b.N)) 1560 b.StopTimer() 1561 }) 1562 1563 b.Run("1", func(b *testing.B) { 1564 b.ReportAllocs() 1565 b.ResetTimer() 1566 for i := 0; i < b.N; i++ { 1567 count := 0 1568 for _, bb := range bs { 1569 if table[bb] { 1570 count++ 1571 } 1572 } 1573 if countG[0] == 0 { 1574 countG[0] = count 1575 } 1576 } 1577 b.SetBytes(int64(b.N)) 1578 b.StopTimer() 1579 }) 1580 1581 b.Run("2", func(b *testing.B) { 1582 xs := []byte{0x85, 0xA0, '\t', '\n', '\v', '\f', '\r', ' '} 1583 b.ReportAllocs() 1584 b.ResetTimer() 1585 for i := 0; i < b.N; i++ { 1586 count := 0 1587 for _, x := range xs[:] { 1588 for i, c := 0, 0; ; { 1589 c = bytes.IndexByte(bs[i:], x) 1590 if c < 0 { 1591 break 1592 } 1593 count++ 1594 i = i + c + 1 1595 for ; bs[i] == x; i++ { 1596 count++ 1597 } 1598 } 1599 } 1600 if countG[1] == 0 { 1601 countG[1] = count 1602 } 1603 } 1604 b.SetBytes(int64(b.N)) 1605 b.StopTimer() 1606 }) 1607 b.Run("2-1", func(b *testing.B) { 1608 xs := []byte{0x85, 0xA0, '\t', '\n', '\v', '\f', '\r'} 1609 b.ReportAllocs() 1610 b.ResetTimer() 1611 for i := 0; i < b.N; i++ { 1612 count := 0 1613 for _, x := range xs[:] { 1614 for i, c := 0, 0; ; { 1615 c = bytes.IndexByte(bs[i:], x) 1616 if c < 0 { 1617 break 1618 } 1619 count++ 1620 i = i + c + 1 1621 for ; bs[i] == x; i++ { 1622 count++ 1623 } 1624 } 1625 } 1626 // for _, b := range bs { 1627 // if b == ' ' { 1628 // count++ 1629 // } 1630 // } 1631 if countG[1] == 0 { 1632 countG[1] = count 1633 } 1634 } 1635 b.SetBytes(int64(b.N)) 1636 b.StopTimer() 1637 }) 1638 b.Run("2-3", func(b *testing.B) { 1639 b.ReportAllocs() 1640 b.ResetTimer() 1641 for i := 0; i < b.N; i++ { 1642 count := 0 1643 for i, c := 0, 0; ; { 1644 c = bytes.IndexByte(bs[i:], '\r') 1645 if c < 0 { 1646 break 1647 } 1648 count++ 1649 i = i + c + 1 1650 } 1651 1652 } 1653 b.SetBytes(int64(b.N)) 1654 b.StopTimer() 1655 }) 1656 b.Run("2-2", func(b *testing.B) { 1657 b.ReportAllocs() 1658 b.ResetTimer() 1659 for i := 0; i < b.N; i++ { 1660 count := 0 1661 for i := 0; i < len(bs); i++ { 1662 if bs[i] == ' ' { 1663 count++ 1664 } 1665 } 1666 if countG[1] == 0 { 1667 countG[1] = count 1668 } 1669 } 1670 b.SetBytes(int64(b.N)) 1671 b.StopTimer() 1672 }) 1673 1674 b.Run("3", func(b *testing.B) { 1675 table := [256]bool{'\t': true, '\n': true, '\v': true, '\f': true, '\r': true, ' ': true, 0x85: true, 0xA0: true} 1676 1677 xs := [4]uint64{} 1678 1679 for i := 0; i < 256; i++ { 1680 if table[i] { 1681 xs[i/64] |= 1 << (uint64(i) % 64) 1682 } 1683 } 1684 b.ReportAllocs() 1685 b.ResetTimer() 1686 for i := 0; i < b.N; i++ { 1687 var count uint64 1688 for _, x := range bs { 1689 // x := uint64(bb) 1690 // if (xs[x/64] & (1 << (x % 64))) > 0 { 1691 // count++ 1692 // } 1693 count += (xs[x/64] >> (x % 64)) & 1 1694 } 1695 if countG[2] == 0 { 1696 countG[2] = int(count) 1697 } 1698 } 1699 b.SetBytes(int64(b.N)) 1700 b.StopTimer() 1701 }) 1702 1703 if countG[0] != countG[1] || countG[0] != countG[2] || countG[0] != countG[3] || 1704 countG[0] != countG[4] || countG[0] != countG[5] || countG[0] != countG[6] { 1705 b.Fatalf("countG:%+v", countG) 1706 } else { 1707 b.Logf("countG:%+v", countG) 1708 } 1709 } 1710 1711 func BenchmarkMapAcess(b *testing.B) { 1712 m := make(map[string][]byte) 1713 keys := make([]string, 200) 1714 for i := range keys { 1715 key := make([]byte, 20) 1716 for i := range key { 1717 key[i] = byte(rand.Uint32()) 1718 } 1719 m[string(key)] = key 1720 keys[i] = string(key) 1721 } 1722 b.Run("1", func(b *testing.B) { 1723 b.ReportAllocs() 1724 for i := 0; i < b.N; i++ { 1725 _ = m[keys[i%len(keys)]] 1726 } 1727 b.SetBytes(int64(b.N)) 1728 b.StopTimer() 1729 }) 1730 } 1731 1732 var j0x = `{ 1733 "id": "7028151259660092936", 1734 "name": { 1735 "zh-CN": "陈三", 1736 "en-US": "" 1737 }, 1738 "avatar": { 1739 "avatar": "https://7b90749e-a6be-4a86-9f9b-7dce3d2ecf5g~?image_size=noop&cut_type=&quality=&format=png&sticker_format=.webp", 1740 "avatar72": "https://7b90749e-a6be-4a86-9f9b-7dce3d2ecf5g~?image_size=72x72&cut_type=&quality=&format=png&sticker_format=.webp", 1741 "avatar240": "https://7b90749e-a6be-4a86-9f9b-7dce3d2ecf5g~?image_size=240x240&cut_type=&quality=&format=png&sticker_format=.webp", 1742 "avatar640": "https://7b90749e-a6be-4a86-9f9b-7dce3d2ecf5g~?image_size=640x640&cut_type=&quality=&format=png&sticker_format=.webp" 1743 }, 1744 "department": { 1745 "id": "6826585686905406989", 1746 "name": { 1747 "zh-CN": "研发部", 1748 "en-US": "RD Department" 1749 } 1750 }, 1751 "email": "", 1752 "mobile": { 1753 "phone": "18030838810", 1754 "code": "86" 1755 }, 1756 "status": { 1757 "accountStatus": false, 1758 "employmentStatus": false, 1759 "registerStatus": false 1760 }, 1761 "employeeType": { 1762 "id": 1, 1763 "name": { 1764 "zh-CN": "正式", 1765 "en-US": "Regular" 1766 }, 1767 "active": true 1768 }, 1769 "isAdmin": false, 1770 "isLeader": false, 1771 "isManager": false, 1772 "isAppManager": false, 1773 "departmentList": { 1774 "id": "6826585686905406989", 1775 "name": { 1776 "zh-CN": "研发部", 1777 "en-US": "RD Department" 1778 } 1779 } 1780 }` 1781 1782 var j0 = `{"id":"7028151259660092936","name":{"zh-CN":"陈三","en-US":""},"avatar":{"avatar":"https://7b90749e-a6be-4a86-9f9b-7dce3d2ecf5g~?image_size=noop&cut_type=&quality=&format=png&sticker_format=.webp","avatar72":"https://7b90749e-a6be-4a86-9f9b-7dce3d2ecf5g~?image_size=72x72&cut_type=&quality=&format=png&sticker_format=.webp","avatar240":"https://7b90749e-a6be-4a86-9f9b-7dce3d2ecf5g~?image_size=240x240&cut_type=&quality=&format=png&sticker_format=.webp","avatar640":"https://7b90749e-a6be-4a86-9f9b-7dce3d2ecf5g~?image_size=640x640&cut_type=&quality=&format=png&sticker_format=.webp"},"department":{"id":"6826585686905406989","name":{"zh-CN":"研发部","en-US":"RD Department"}},"email":"","mobile":{"phone":"18030838810","code":"86"},"status":{"accountStatus":false,"employmentStatus":false,"registerStatus":false},"employeeType":{"id":1,"name":{"zh-CN":"正式","en-US":"Regular"},"active":true},"isAdmin":false,"isLeader":false,"isManager":false,"isAppManager":false,"departmentList":{"id":"6826585686905406989","name":{"zh-CN":"研发部","en-US":"RD Department"}}}` 1783 1784 type J0 struct { 1785 ID string `json:"id"` 1786 Name struct { 1787 ZhCN string `json:"zh-CN"` 1788 EnUS string `json:"en-US"` 1789 } `json:"name"` 1790 Avatar struct { 1791 Avatar string `json:"avatar"` 1792 Avatar72 string `json:"avatar72"` 1793 Avatar240 string `json:"avatar240"` 1794 Avatar640 string `json:"avatar640"` 1795 } `json:"avatar"` 1796 Department struct { 1797 ID string `json:"id"` 1798 Name struct { 1799 ZhCN string `json:"zh-CN"` 1800 EnUS string `json:"en-US"` 1801 } `json:"name"` 1802 } `json:"department"` 1803 Email string `json:"email"` 1804 Mobile struct { 1805 Phone string `json:"phone"` 1806 Code string `json:"code"` 1807 } `json:"mobile"` 1808 Status struct { 1809 AccountStatus bool `json:"accountStatus"` 1810 EmploymentStatus bool `json:"employmentStatus"` 1811 RegisterStatus bool `json:"registerStatus"` 1812 } `json:"status"` 1813 EmployeeType struct { 1814 ID int `json:"id"` 1815 Name struct { 1816 ZhCN string `json:"zh-CN"` 1817 EnUS string `json:"en-US"` 1818 } `json:"name"` 1819 Active bool `json:"active"` 1820 } `json:"employeeType"` 1821 IsAdmin bool `json:"isAdmin"` 1822 IsLeader bool `json:"isLeader"` 1823 IsManager bool `json:"isManager"` 1824 IsAppManager bool `json:"isAppManager"` 1825 DepartmentList struct { 1826 ID string `json:"id"` 1827 Name struct { 1828 ZhCN string `json:"zh-CN"` 1829 EnUS string `json:"en-US"` 1830 } `json:"name"` 1831 } `json:"departmentList"` 1832 }