github.com/lxt1045/json@v0.0.0-20231013032136-54d6b1d6e525/struct_test.go (about)

     1  package json
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"path/filepath"
     7  	"runtime"
     8  	"strconv"
     9  	"sync"
    10  	"testing"
    11  
    12  	"github.com/bytedance/sonic"
    13  	"github.com/lxt1045/json/testdata"
    14  	asrt "github.com/stretchr/testify/assert"
    15  )
    16  
    17  func TestStruct(t *testing.T) {
    18  	type Anonymous struct {
    19  		Count int `json:"count"`
    20  		X     string
    21  	}
    22  	fLine := func() string {
    23  		_, file, line, _ := runtime.Caller(1)
    24  		_, file = filepath.Split(file)
    25  		return file + ":" + strconv.Itoa(line)
    26  	}
    27  	idx := -1
    28  
    29  	datas := []struct {
    30  		name   string
    31  		bs     string
    32  		target string
    33  		data   interface{}
    34  	}{
    35  		{
    36  			name:   "struct:" + fLine(),
    37  			bs:     `{"out": -0.1 , "struct_0": [{ "count":8,"Anonymous":{"X":"xxx","Count":1}}]}`,
    38  			target: `{"out":-0.1,"struct_0":[{"count":8,"Anonymous":{"count":0,"X":"xxx"}}]}`,
    39  			data: &struct {
    40  				Out    float32 `json:"out"`
    41  				Struct []struct {
    42  					Count     int `json:"count"`
    43  					Anonymous Anonymous
    44  				} `json:"struct_0"`
    45  			}{},
    46  		},
    47  		{
    48  			name:   "struct:" + fLine(),
    49  			bs:     `{"out": 11 , "struct_0": [{ "count":8,"Anonymous":{"X":"xxx","Count":1}}]}`,
    50  			target: `{"out":11,"struct_0":[{"count":8,"Anonymous":{"count":0,"X":"xxx"}}]}`,
    51  			data: &struct {
    52  				Out    int `json:"out"`
    53  				Struct []struct {
    54  					Count     int `json:"count"`
    55  					Anonymous Anonymous
    56  				} `json:"struct_0"`
    57  			}{},
    58  		},
    59  		{
    60  			name:   "interface:" + fLine(),
    61  			bs:     `{"out":88,"struct_0":{"a":"<a href=\"//itunes.apple.com/us/app/twitter/id409789998?mt=12%5C%22\" rel=\"\\\"nofollow\\\"\">Twitter for Mac</a>"}}`,
    62  			target: `{"out":88,"struct_0":{"a":"\u003ca href=\"//itunes.apple.com/us/app/twitter/id409789998?mt=12%5C%22\" rel=\"\\\"nofollow\\\"\"\u003eTwitter for Mac\u003c/a\u003e"}}`,
    63  			data: &struct {
    64  				Out    int         `json:"out"`
    65  				Struct interface{} `json:"struct_0"`
    66  			}{},
    67  		},
    68  		{
    69  			name:   "interface:" + fLine(),
    70  			bs:     `{"out":"<a href=\"//itunes.apple.com/us/app/twitter/id409789998?mt=12%5C%22\" rel=\"\\\"nofollow\\\"\">Twitter for Mac</a>"}`,
    71  			target: "{\"out\":\"\\u003ca href=\\\"//itunes.apple.com/us/app/twitter/id409789998?mt=12%5C%22\\\" rel=\\\"\\\\\\\"nofollow\\\\\\\"\\\"\\u003eTwitter for Mac\\u003c/a\\u003e\"}",
    72  			data: &struct {
    73  				Out string `json:"out"`
    74  			}{},
    75  		},
    76  		{
    77  			name:   "interface:" + fLine(),
    78  			bs:     `{"out": 11 , "struct_0": { "count":8}}`,
    79  			target: `{"out":11,"struct_0":{"count":8}}`,
    80  			data: &struct {
    81  				Out    int         `json:"out"`
    82  				Struct interface{} `json:"struct_0"`
    83  			}{},
    84  		},
    85  		{
    86  			name:   "map" + fLine(),
    87  			bs:     `{"out": 11 , "map_0": { "count":8,"y":"yyy"}}`,
    88  			target: `{"out":11,"map_0":{"count":8,"y":"yyy"}}`,
    89  			data:   &map[string]interface{}{},
    90  		},
    91  
    92  		// 匿名类型; 指针匿名类型
    93  		{
    94  			name:   "struct-Anonymous:" + fLine(),
    95  			bs:     `{"out": 11 , "count":8,"X":"xxx"}`,
    96  			target: `{"out":11,"count":8,"X":"xxx"}`,
    97  			data: &struct {
    98  				Out int `json:"out"`
    99  				Anonymous
   100  			}{},
   101  		},
   102  		{
   103  			name:   "struct:" + fLine(),
   104  			bs:     `{"out": 11 , "struct_0": { "count":8}}`,
   105  			target: `{"out":11,"struct_0":{"count":8}}`,
   106  			data: &struct {
   107  				Out    int `json:"out"`
   108  				Struct struct {
   109  					Count int `json:"count"`
   110  				} `json:"struct_0"`
   111  			}{},
   112  		},
   113  		{
   114  			name:   "struct:" + fLine(),
   115  			bs:     `{"out": 11 , "struct_0": { "count":8,"slice":[1,2,3]}}`,
   116  			target: `{"out":11,"struct_0":{"count":8,"slice":[1,2,3]}}`,
   117  			data: &struct {
   118  				Out    int `json:"out"`
   119  				Struct struct {
   120  					Count int   `json:"count"`
   121  					Slice []int `json:"slice"`
   122  				} `json:"struct_0"`
   123  			}{},
   124  		},
   125  		{
   126  			name:   "slice:" + fLine(),
   127  			bs:     `{"count":8 , "slice":[1,2,3] }`,
   128  			target: `{"count":8,"slice":[1,2,3]}`,
   129  			data: &struct {
   130  				Count int   `json:"count"`
   131  				Slice []int `json:"slice"`
   132  			}{},
   133  		},
   134  		{
   135  			name:   "bool:" + fLine(),
   136  			bs:     `{"count":true , "false_0":false }`,
   137  			target: `{"count":true,"false_0":false}`,
   138  			data: &struct {
   139  				Count bool `json:"count"`
   140  				False bool `json:"false_0"`
   141  			}{},
   142  		},
   143  		{
   144  			name:   "bool-ptr:" + fLine(),
   145  			bs:     `{"count":true , "false_0":false }`,
   146  			target: `{"count":true,"false_0":false}`,
   147  			data: &struct {
   148  				Count *bool `json:"count"`
   149  				False *bool `json:"false_0"`
   150  			}{},
   151  		},
   152  		{
   153  			name:   "bool-ptr-null:" + fLine(),
   154  			bs:     `{"count":true , "false_0":null }`,
   155  			target: `{"count":true,"false_0":null}`,
   156  			data: &struct {
   157  				Count *bool `json:"count"`
   158  				False *bool `json:"false_0"`
   159  			}{},
   160  		},
   161  		{
   162  			name:   "bool-ptr-empty:" + fLine(),
   163  			bs:     `{"count":true }`,
   164  			target: `{"count":true,"false_0":null}`,
   165  			data: &struct {
   166  				Count *bool `json:"count"`
   167  				False *bool `json:"false_0"`
   168  			}{},
   169  		},
   170  		{
   171  			name:   "float64:" + fLine(),
   172  			bs:     `{"count":8.11 }`,
   173  			target: `{"count":8.11}`,
   174  			data: &struct {
   175  				Count float64 `json:"count"`
   176  			}{},
   177  		},
   178  		{
   179  			name:   "float64-ptr:" + fLine(),
   180  			bs:     `{"count":8.11 }`,
   181  			target: `{"count":8.11}`,
   182  			data: &struct {
   183  				Count *float64 `json:"count"`
   184  			}{},
   185  		},
   186  		{
   187  			name:   "int-ptr:" + fLine(),
   188  			bs:     `{"count":8 }`,
   189  			target: `{"count":8}`,
   190  			data: &struct {
   191  				Count *int `json:"count"`
   192  			}{},
   193  		},
   194  		{
   195  			name:   "int:" + fLine(),
   196  			bs:     `{"count":8 }`,
   197  			target: `{"count":8}`,
   198  			data: &struct {
   199  				Count int `json:"count"`
   200  			}{},
   201  		},
   202  		{
   203  			name:   "string-ptr:" + fLine(),
   204  			bs:     `{ "ZHCN":"chinese"}`,
   205  			target: `{"ZHCN":"chinese"}`,
   206  			data: &struct {
   207  				ZHCN *string
   208  			}{},
   209  		},
   210  		{
   211  			name:   "string-notag:" + fLine(),
   212  			bs:     `{ "ZHCN":"chinese"}`,
   213  			target: `{"ZHCN":"chinese"}`,
   214  			data: &struct {
   215  				ZHCN string
   216  			}{},
   217  		},
   218  		{
   219  			name:   "string:" + fLine(),
   220  			bs:     `{ "ZH_CN":"chinese", "ENUS":"English", "count":8 }`,
   221  			target: `{"ZH_CN":"chinese"}`,
   222  			data: &struct {
   223  				ZHCN string `json:"ZH_CN"`
   224  			}{},
   225  		},
   226  	}
   227  	if idx >= 0 {
   228  		datas = datas[idx : idx+1]
   229  	}
   230  
   231  	for i, d := range datas {
   232  		t.Run(d.name, func(t *testing.T) {
   233  			err := Unmarshal([]byte(d.bs), d.data)
   234  			if err != nil {
   235  				t.Fatalf("[%d]%s, error:%v\n", i, d.name, err)
   236  			}
   237  			bs, err := json.Marshal(d.data)
   238  			if err != nil {
   239  				t.Fatalf("i:%d, %s:%v\n", i, d.name, err)
   240  			}
   241  			if m, ok := (d.data).(*map[string]interface{}); ok {
   242  				var mm map[string]interface{}
   243  				json.Unmarshal([]byte(d.target), &mm)
   244  				for k, v := range *m {
   245  					asrt.Equalf(t, mm[k], v, fmt.Sprintf("i:%d,%s", i, d.name))
   246  				}
   247  				for k, v := range mm {
   248  					asrt.Equalf(t, (*m)[k], v, fmt.Sprintf("i:%d,%s", i, d.name))
   249  				}
   250  
   251  				t.Logf("\n%s\n%s", string(d.target), string(bs))
   252  				// asrt.EqualValuesf(t, d.target, string(bs), d.name)
   253  			} else if _, ok := (d.data).(*interface{}); ok {
   254  				t.Logf("\n%s\n%s", string(d.target), string(bs))
   255  				// asrt.EqualValuesf(t, d.target, string(bs), d.name)
   256  			} else {
   257  				asrt.Equalf(t, d.target, string(bs), fmt.Sprintf("i:%d,%s", i, d.name))
   258  			}
   259  
   260  			runtime.GC()
   261  			_ = fmt.Sprintf("d :%+v", d)
   262  		})
   263  	}
   264  }
   265  
   266  func TestStructMarshalInterface(t *testing.T) {
   267  	type st struct {
   268  		Count string `json:"count"`
   269  		X     interface{}
   270  	}
   271  	s := &st{
   272  		Count: "xxx",
   273  		X: st{
   274  			Count: "xxx",
   275  			X:     "xxx",
   276  		},
   277  	}
   278  	bs, err := json.Marshal(&s)
   279  	if err != nil {
   280  		t.Fatal(err)
   281  	}
   282  	t.Logf("json:%s", string(bs))
   283  }
   284  
   285  func TestStructMarshal(t *testing.T) {
   286  	type Anonymous struct {
   287  		Count int `json:"count"`
   288  		X     string
   289  	}
   290  	fLine := func() string {
   291  		_, file, line, _ := runtime.Caller(1)
   292  		_, file = filepath.Split(file)
   293  		return file + ":" + strconv.Itoa(line)
   294  	}
   295  	idx := -5
   296  
   297  	datas := []struct {
   298  		name    string
   299  		bs      string
   300  		target  string
   301  		target2 string
   302  		data    interface{}
   303  	}{
   304  		{
   305  			name:   "struct:" + fLine(),
   306  			bs:     `{"out": 11 , "struct_0": { "count":8}}`,
   307  			target: `{"out":11,"struct_0":{"count":8}}`,
   308  			data: &struct {
   309  				Out    int                    `json:"out"`
   310  				Struct map[string]interface{} `json:"struct_0"`
   311  			}{},
   312  		},
   313  		{
   314  			name:    "interface:" + fLine(),
   315  			bs:      `{"out":88,"struct_0":{"a":"<a href=\"//itunes.apple.com/us/app/twitter/id409789998?mt=12%5C%22\" rel=\"\\\"nofollow\\\"\">Twitter for Mac</a>"}}`,
   316  			target:  `{"out":88,"struct_0":{"a":"\u003ca href=\"//itunes.apple.com/us/app/twitter/id409789998?mt=12%5C%22\" rel=\"\\\"nofollow\\\"\"\u003eTwitter for Mac\u003c/a\u003e"}}`,
   317  			target2: `{"out":88,"struct_0":{"a":"<a href="//itunes.apple.com/us/app/twitter/id409789998?mt=12%5C%22" rel="\"nofollow\"">Twitter for Mac</a>"}}`,
   318  			data: &struct {
   319  				Out    int         `json:"out"`
   320  				Struct interface{} `json:"struct_0"`
   321  			}{},
   322  		},
   323  		{
   324  			name:    "interface:" + fLine(),
   325  			bs:      `{"out":"<a href=\"//itunes.apple.com/us/app/twitter/id409789998?mt=12%5C%22\" rel=\"\\\"nofollow\\\"\">Twitter for Mac</a>"}`,
   326  			target:  "{\"out\":\"\\u003ca href=\\\"//itunes.apple.com/us/app/twitter/id409789998?mt=12%5C%22\\\" rel=\\\"\\\\\\\"nofollow\\\\\\\"\\\"\\u003eTwitter for Mac\\u003c/a\\u003e\"}",
   327  			target2: `{"out":"<a href="//itunes.apple.com/us/app/twitter/id409789998?mt=12%5C%22" rel="\"nofollow\"">Twitter for Mac</a>"}`,
   328  			data: &struct {
   329  				Out string `json:"out"`
   330  			}{},
   331  		},
   332  		{
   333  			name:   "interface:" + fLine(),
   334  			bs:     `{"out": 11 , "struct_0": { "count":8}}`,
   335  			target: `{"out":11,"struct_0":{"count":8}}`,
   336  			data: &struct {
   337  				Out    int         `json:"out"`
   338  				Struct interface{} `json:"struct_0"`
   339  			}{},
   340  		},
   341  		{
   342  			name:   "map" + fLine(),
   343  			bs:     `{"out": 11 , "map_0": { "count":8,"y":"yyy"}}`,
   344  			target: `{"out":11,"map_0":{"count":8,"y":"yyy"}}`,
   345  			data:   &map[string]interface{}{},
   346  		},
   347  
   348  		// 匿名类型; 指针匿名类型
   349  		{
   350  			name:   "struct-Anonymous:" + fLine(),
   351  			bs:     `{"out": 11 , "count":8,"X":"xxx"}`,
   352  			target: `{"out":11,"count":8,"X":"xxx"}`,
   353  			data: &struct {
   354  				Out int `json:"out"`
   355  				Anonymous
   356  			}{},
   357  		},
   358  		{
   359  			name:   "struct:" + fLine(),
   360  			bs:     `{"out": 11 , "struct_0": { "count":8}}`,
   361  			target: `{"out":11,"struct_0":{"count":8}}`,
   362  			data: &struct {
   363  				Out    int `json:"out"`
   364  				Struct struct {
   365  					Count int `json:"count"`
   366  				} `json:"struct_0"`
   367  			}{},
   368  		},
   369  		{
   370  			name:   "struct:" + fLine(),
   371  			bs:     `{"out": 11 , "struct_0": { "count":8,"slice":[1,2,3]}}`,
   372  			target: `{"out":11,"struct_0":{"count":8,"slice":[1,2,3]}}`,
   373  			data: &struct {
   374  				Out    int `json:"out"`
   375  				Struct struct {
   376  					Count int   `json:"count"`
   377  					Slice []int `json:"slice"`
   378  				} `json:"struct_0"`
   379  			}{},
   380  		},
   381  		{
   382  			name:   "slice:" + fLine(),
   383  			bs:     `{"count":8 , "slice":[1,2,3] }`,
   384  			target: `{"count":8,"slice":[1,2,3]}`,
   385  			data: &struct {
   386  				Count int   `json:"count"`
   387  				Slice []int `json:"slice"`
   388  			}{},
   389  		},
   390  		{
   391  			name:   "bool:" + fLine(),
   392  			bs:     `{"count":true , "false_0":false }`,
   393  			target: `{"count":true,"false_0":false}`,
   394  			data: &struct {
   395  				Count bool `json:"count"`
   396  				False bool `json:"false_0"`
   397  			}{},
   398  		},
   399  		{
   400  			name:   "bool-ptr:" + fLine(),
   401  			bs:     `{"count":true , "false_0":false }`,
   402  			target: `{"count":true,"false_0":false}`,
   403  			data: &struct {
   404  				Count *bool `json:"count"`
   405  				False *bool `json:"false_0"`
   406  			}{},
   407  		},
   408  		{
   409  			name:   "bool-ptr-null:" + fLine(),
   410  			bs:     `{"count":true , "false_0":null }`,
   411  			target: `{"count":true,"false_0":null}`,
   412  			data: &struct {
   413  				Count *bool `json:"count"`
   414  				False *bool `json:"false_0"`
   415  			}{},
   416  		},
   417  		{
   418  			name:   "bool-ptr-empty:" + fLine(),
   419  			bs:     `{"count":true }`,
   420  			target: `{"count":true,"false_0":null}`,
   421  			data: &struct {
   422  				Count *bool `json:"count"`
   423  				False *bool `json:"false_0"`
   424  			}{},
   425  		},
   426  		{
   427  			name:   "float64:" + fLine(),
   428  			bs:     `{"count":8.11 }`,
   429  			target: `{"count":8.11}`,
   430  			data: &struct {
   431  				Count float64 `json:"count"`
   432  			}{},
   433  		},
   434  		{
   435  			name:   "float64-ptr:" + fLine(),
   436  			bs:     `{"count":8.11 }`,
   437  			target: `{"count":8.11}`,
   438  			data: &struct {
   439  				Count *float64 `json:"count"`
   440  			}{},
   441  		},
   442  		{
   443  			name:   "int-ptr:" + fLine(),
   444  			bs:     `{"count":8 }`,
   445  			target: `{"count":8}`,
   446  			data: &struct {
   447  				Count *int `json:"count"`
   448  			}{},
   449  		},
   450  		{
   451  			name:   "int:" + fLine(),
   452  			bs:     `{"count":8 }`,
   453  			target: `{"count":8}`,
   454  			data: &struct {
   455  				Count int `json:"count"`
   456  			}{},
   457  		},
   458  		{
   459  			name:   "string-ptr:" + fLine(),
   460  			bs:     `{ "ZHCN":"chinese"}`,
   461  			target: `{"ZHCN":"chinese"}`,
   462  			data: &struct {
   463  				ZHCN *string
   464  			}{},
   465  		},
   466  		{
   467  			name:   "string-notag:" + fLine(),
   468  			bs:     `{ "ZHCN":"chinese"}`,
   469  			target: `{"ZHCN":"chinese"}`,
   470  			data: &struct {
   471  				ZHCN string
   472  			}{},
   473  		},
   474  		{
   475  			name:   "string:" + fLine(),
   476  			bs:     `{ "ZH_CN":"chinese", "ENUS":"English", "count":8 }`,
   477  			target: `{"ZH_CN":"chinese"}`,
   478  			data: &struct {
   479  				ZHCN string `json:"ZH_CN"`
   480  			}{},
   481  		},
   482  	}
   483  	if idx >= 0 {
   484  		datas = datas[idx : idx+1]
   485  	}
   486  
   487  	for i, d := range datas {
   488  		t.Run(d.name, func(t *testing.T) {
   489  			err := Unmarshal([]byte(d.bs), d.data)
   490  			if err != nil {
   491  				t.Fatalf("[%d]%s, error:%v\n", i, d.name, err)
   492  			}
   493  			bs, err := json.Marshal(d.data)
   494  			if err != nil {
   495  				t.Fatalf("i:%d, %s:%v\n", i, d.name, err)
   496  			}
   497  			if _, ok := (d.data).(*map[string]interface{}); ok {
   498  				t.Logf("\n%s\n%s", string(d.target), string(bs))
   499  				// asrt.EqualValuesf(t, d.target, string(bs), d.name)
   500  			} else if _, ok := (d.data).(*interface{}); ok {
   501  				t.Logf("\n%s\n%s", string(d.target), string(bs))
   502  				// asrt.EqualValuesf(t, d.target, string(bs), d.name)
   503  			} else {
   504  				asrt.Equalf(t, d.target, string(bs), fmt.Sprintf("i:%d,%s", i, d.name))
   505  			}
   506  
   507  			runtime.GC()
   508  			_ = fmt.Sprintf("d :%+v", d)
   509  
   510  			bsOut, err := Marshal(d.data)
   511  			if err != nil {
   512  				t.Fatalf("i:%d, %s:%v\n", i, d.name, err)
   513  			}
   514  			if _, ok := (d.data).(*map[string]interface{}); ok {
   515  				t.Logf("\n%s\n%s", string(d.target), string(bs))
   516  				// asrt.EqualValuesf(t, d.target, string(bs), d.name)
   517  			} else if _, ok := (d.data).(*interface{}); ok {
   518  				t.Logf("\n%s\n%s", string(d.target), string(bs))
   519  				// asrt.EqualValuesf(t, d.target, string(bs), d.name)
   520  			} else {
   521  				target := d.target2
   522  				if target == "" {
   523  					target = d.target
   524  				}
   525  				asrt.Equalf(t, target, string(bsOut), fmt.Sprintf("i:%d,%s", i, d.name))
   526  			}
   527  
   528  		})
   529  	}
   530  }
   531  
   532  func BenchmarkTestLoop(b *testing.B) {
   533  	loop := 10000000000
   534  	b.Run("loop1", func(b *testing.B) {
   535  		for i := 0; i < b.N; i++ {
   536  			for j := 0; j < loop; j++ {
   537  			}
   538  		}
   539  	})
   540  	b.Run("loop1", func(b *testing.B) {
   541  		for i := 0; i < b.N; i++ {
   542  			for j := 0; j < loop; j++ {
   543  			}
   544  		}
   545  	})
   546  	b.Run("loop1", func(b *testing.B) {
   547  		for i := 0; i < b.N; i++ {
   548  			for j := 0; j < loop; j++ {
   549  			}
   550  			for j := 0; j < loop; j++ {
   551  			}
   552  		}
   553  	})
   554  }
   555  
   556  func TestStructST(t *testing.T) {
   557  	type ST struct {
   558  		Count int `json:"count"`
   559  		X     string
   560  		ST    *ST
   561  	}
   562  	st := ST{
   563  		Count: 22,
   564  		X:     "xxx",
   565  		ST: &ST{
   566  			Count: 22,
   567  			X:     "xxx",
   568  		},
   569  	}
   570  	bs, err := json.Marshal(&st)
   571  	if err != nil {
   572  		t.Fatal(err)
   573  	}
   574  	t.Logf(string(bs))
   575  
   576  	t.Run("qq", func(t *testing.T) {
   577  		// err := Unmarshal([]byte(d.bs), d.data)
   578  		// if err != nil {
   579  		// 	t.Fatalf("[%d]%s, error:%v\n", i, d.name, err)
   580  		// }
   581  		st2 := ST{}
   582  		err := json.Unmarshal(bs, &st2)
   583  		if err != nil {
   584  			t.Fatal(err)
   585  		}
   586  		bs, err := json.Marshal(&st2)
   587  		if err != nil {
   588  			t.Fatal(err)
   589  		}
   590  		t.Logf("%+v", string(bs))
   591  	})
   592  
   593  	t.Run("qq1", func(t *testing.T) {
   594  		st2 := ST{}
   595  		err := Unmarshal(bs, &st2)
   596  		if err != nil {
   597  			t.Fatal(err)
   598  		}
   599  		bs, err := json.Marshal(&st2)
   600  		if err != nil {
   601  			t.Fatal(err)
   602  		}
   603  		t.Logf("%+v", string(bs))
   604  	})
   605  }
   606  
   607  func BenchmarkParallelSafety(b *testing.B) {
   608  	bs := []byte(testdata.BookData)
   609  	str := string(bs)
   610  	d := testdata.Book{}
   611  	err := Unmarshal(bs, &d)
   612  	if err != nil {
   613  		b.Fatal(err)
   614  	}
   615  	sonic.UnmarshalString(str, &d)
   616  
   617  	var wg sync.WaitGroup
   618  	runtime.GC()
   619  	for x := 0; x < 100; x++ {
   620  		go func() {
   621  			wg.Add(1)
   622  			defer wg.Done()
   623  			runtime.Gosched()
   624  			for i := 0; i < b.N; i++ {
   625  				d := testdata.Book{}
   626  				_ = UnmarshalString(str, &d)
   627  			}
   628  		}()
   629  	}
   630  	b.Run("decode-lxt", func(b *testing.B) {
   631  		b.SetBytes(int64(len(bs)))
   632  		// b.ReportAllocs()
   633  		b.ResetTimer()
   634  		for i := 0; i < b.N; i++ {
   635  			d := testdata.Book{}
   636  			_ = UnmarshalString(str, &d)
   637  		}
   638  	})
   639  	wg.Wait()
   640  
   641  	for x := 0; x < 100; x++ {
   642  		go func() {
   643  			wg.Add(1)
   644  			defer wg.Done()
   645  			runtime.Gosched()
   646  			for i := 0; i < b.N; i++ {
   647  				d := testdata.Book{}
   648  				_ = UnmarshalString(str, &d)
   649  			}
   650  		}()
   651  	}
   652  	runtime.GC()
   653  	b.Run("decode-parallel-lxt", func(b *testing.B) {
   654  		b.SetBytes(int64(len(bs)))
   655  		// b.ReportAllocs()
   656  		b.ResetTimer()
   657  		b.RunParallel(func(pb *testing.PB) {
   658  			for pb.Next() {
   659  				d := testdata.Book{}
   660  				_ = UnmarshalString(str, &d)
   661  			}
   662  		})
   663  
   664  	})
   665  
   666  	wg.Wait()
   667  	// encode
   668  
   669  	for x := 0; x < 100; x++ {
   670  		go func() {
   671  			wg.Add(1)
   672  			defer wg.Done()
   673  			runtime.Gosched()
   674  			for i := 0; i < b.N; i++ {
   675  				_, _ = Marshal(&d)
   676  			}
   677  		}()
   678  	}
   679  	runtime.GC()
   680  	b.Run("encode-lxt", func(b *testing.B) {
   681  		b.SetBytes(int64(len(bs)))
   682  		// b.ReportAllocs()
   683  		b.ResetTimer()
   684  		for i := 0; i < b.N; i++ {
   685  			_, _ = Marshal(&d)
   686  		}
   687  	})
   688  
   689  	wg.Wait()
   690  
   691  	for x := 0; x < 100; x++ {
   692  		go func() {
   693  			wg.Add(1)
   694  			defer wg.Done()
   695  			for i := 0; i < b.N; i++ {
   696  				d := testdata.Book{}
   697  				_, _ = Marshal(&d)
   698  			}
   699  		}()
   700  	}
   701  	runtime.GC()
   702  	b.Run("encode-parallel-lxt", func(b *testing.B) {
   703  		b.SetBytes(int64(len(bs)))
   704  		// b.ReportAllocs()
   705  		b.ResetTimer()
   706  		b.RunParallel(func(pb *testing.PB) {
   707  			for pb.Next() {
   708  				_, _ = Marshal(&d)
   709  			}
   710  		})
   711  	})
   712  }