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  }