...

Source file src/github.com/pelletier/go-toml/v2/benchmark/benchmark_test.go

Documentation: github.com/pelletier/go-toml/v2/benchmark

     1  package benchmark_test
     2  
     3  import (
     4  	"bytes"
     5  	"io/ioutil"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/pelletier/go-toml/v2"
    10  	"github.com/stretchr/testify/require"
    11  )
    12  
    13  func TestUnmarshalSimple(t *testing.T) {
    14  	doc := []byte(`A = "hello"`)
    15  	d := struct {
    16  		A string
    17  	}{}
    18  
    19  	err := toml.Unmarshal(doc, &d)
    20  	if err != nil {
    21  		panic(err)
    22  	}
    23  }
    24  
    25  func BenchmarkUnmarshal(b *testing.B) {
    26  	b.Run("SimpleDocument", func(b *testing.B) {
    27  		doc := []byte(`A = "hello"`)
    28  
    29  		b.Run("struct", func(b *testing.B) {
    30  			b.SetBytes(int64(len(doc)))
    31  			b.ReportAllocs()
    32  			b.ResetTimer()
    33  
    34  			for i := 0; i < b.N; i++ {
    35  				d := struct {
    36  					A string
    37  				}{}
    38  
    39  				err := toml.Unmarshal(doc, &d)
    40  				if err != nil {
    41  					panic(err)
    42  				}
    43  			}
    44  		})
    45  
    46  		b.Run("map", func(b *testing.B) {
    47  			b.SetBytes(int64(len(doc)))
    48  			b.ReportAllocs()
    49  			b.ResetTimer()
    50  
    51  			for i := 0; i < b.N; i++ {
    52  				d := map[string]interface{}{}
    53  				err := toml.Unmarshal(doc, &d)
    54  				if err != nil {
    55  					panic(err)
    56  				}
    57  			}
    58  		})
    59  	})
    60  
    61  	b.Run("ReferenceFile", func(b *testing.B) {
    62  		bytes, err := ioutil.ReadFile("benchmark.toml")
    63  		if err != nil {
    64  			b.Fatal(err)
    65  		}
    66  
    67  		b.Run("struct", func(b *testing.B) {
    68  			b.SetBytes(int64(len(bytes)))
    69  			b.ReportAllocs()
    70  			b.ResetTimer()
    71  			for i := 0; i < b.N; i++ {
    72  				d := benchmarkDoc{}
    73  				err := toml.Unmarshal(bytes, &d)
    74  				if err != nil {
    75  					panic(err)
    76  				}
    77  			}
    78  		})
    79  
    80  		b.Run("map", func(b *testing.B) {
    81  			b.SetBytes(int64(len(bytes)))
    82  			b.ReportAllocs()
    83  			b.ResetTimer()
    84  			for i := 0; i < b.N; i++ {
    85  				d := map[string]interface{}{}
    86  				err := toml.Unmarshal(bytes, &d)
    87  				if err != nil {
    88  					panic(err)
    89  				}
    90  			}
    91  		})
    92  	})
    93  
    94  	b.Run("HugoFrontMatter", func(b *testing.B) {
    95  		b.SetBytes(int64(len(hugoFrontMatterbytes)))
    96  		b.ReportAllocs()
    97  		b.ResetTimer()
    98  		for i := 0; i < b.N; i++ {
    99  			d := map[string]interface{}{}
   100  			err := toml.Unmarshal(hugoFrontMatterbytes, &d)
   101  			if err != nil {
   102  				panic(err)
   103  			}
   104  		}
   105  	})
   106  }
   107  
   108  func marshal(v interface{}) ([]byte, error) {
   109  	var b bytes.Buffer
   110  	enc := toml.NewEncoder(&b)
   111  	err := enc.Encode(v)
   112  	return b.Bytes(), err
   113  }
   114  
   115  func BenchmarkMarshal(b *testing.B) {
   116  	b.Run("SimpleDocument", func(b *testing.B) {
   117  		doc := []byte(`A = "hello"`)
   118  
   119  		b.Run("struct", func(b *testing.B) {
   120  			d := struct {
   121  				A string
   122  			}{}
   123  
   124  			err := toml.Unmarshal(doc, &d)
   125  			if err != nil {
   126  				panic(err)
   127  			}
   128  
   129  			b.ReportAllocs()
   130  			b.ResetTimer()
   131  
   132  			var out []byte
   133  
   134  			for i := 0; i < b.N; i++ {
   135  				out, err = marshal(d)
   136  				if err != nil {
   137  					panic(err)
   138  				}
   139  			}
   140  
   141  			b.SetBytes(int64(len(out)))
   142  		})
   143  
   144  		b.Run("map", func(b *testing.B) {
   145  			d := map[string]interface{}{}
   146  			err := toml.Unmarshal(doc, &d)
   147  			if err != nil {
   148  				panic(err)
   149  			}
   150  
   151  			b.ReportAllocs()
   152  			b.ResetTimer()
   153  
   154  			var out []byte
   155  
   156  			for i := 0; i < b.N; i++ {
   157  				out, err = marshal(d)
   158  				if err != nil {
   159  					panic(err)
   160  				}
   161  			}
   162  
   163  			b.SetBytes(int64(len(out)))
   164  		})
   165  	})
   166  
   167  	b.Run("ReferenceFile", func(b *testing.B) {
   168  		bytes, err := ioutil.ReadFile("benchmark.toml")
   169  		if err != nil {
   170  			b.Fatal(err)
   171  		}
   172  
   173  		b.Run("struct", func(b *testing.B) {
   174  			d := benchmarkDoc{}
   175  			err := toml.Unmarshal(bytes, &d)
   176  			if err != nil {
   177  				panic(err)
   178  			}
   179  			b.ReportAllocs()
   180  			b.ResetTimer()
   181  
   182  			var out []byte
   183  
   184  			for i := 0; i < b.N; i++ {
   185  				out, err = marshal(d)
   186  				if err != nil {
   187  					panic(err)
   188  				}
   189  			}
   190  
   191  			b.SetBytes(int64(len(out)))
   192  		})
   193  
   194  		b.Run("map", func(b *testing.B) {
   195  			d := map[string]interface{}{}
   196  			err := toml.Unmarshal(bytes, &d)
   197  			if err != nil {
   198  				panic(err)
   199  			}
   200  
   201  			b.ReportAllocs()
   202  			b.ResetTimer()
   203  
   204  			var out []byte
   205  			for i := 0; i < b.N; i++ {
   206  				out, err = marshal(d)
   207  				if err != nil {
   208  					panic(err)
   209  				}
   210  			}
   211  
   212  			b.SetBytes(int64(len(out)))
   213  		})
   214  	})
   215  
   216  	b.Run("HugoFrontMatter", func(b *testing.B) {
   217  		d := map[string]interface{}{}
   218  		err := toml.Unmarshal(hugoFrontMatterbytes, &d)
   219  		if err != nil {
   220  			panic(err)
   221  		}
   222  
   223  		b.ReportAllocs()
   224  		b.ResetTimer()
   225  
   226  		var out []byte
   227  
   228  		for i := 0; i < b.N; i++ {
   229  			out, err = marshal(d)
   230  			if err != nil {
   231  				panic(err)
   232  			}
   233  		}
   234  
   235  		b.SetBytes(int64(len(out)))
   236  	})
   237  }
   238  
   239  type benchmarkDoc struct {
   240  	Table struct {
   241  		Key      string
   242  		Subtable struct {
   243  			Key string
   244  		}
   245  		Inline struct {
   246  			Name struct {
   247  				First string
   248  				Last  string
   249  			}
   250  			Point struct {
   251  				X int64
   252  				Y int64
   253  			}
   254  		}
   255  	}
   256  	String struct {
   257  		Basic struct {
   258  			Basic string
   259  		}
   260  		Multiline struct {
   261  			Key1      string
   262  			Key2      string
   263  			Key3      string
   264  			Continued struct {
   265  				Key1 string
   266  				Key2 string
   267  				Key3 string
   268  			}
   269  		}
   270  		Literal struct {
   271  			Winpath   string
   272  			Winpath2  string
   273  			Quoted    string
   274  			Regex     string
   275  			Multiline struct {
   276  				Regex2 string
   277  				Lines  string
   278  			}
   279  		}
   280  	}
   281  	Integer struct {
   282  		Key1        int64
   283  		Key2        int64
   284  		Key3        int64
   285  		Key4        int64
   286  		Underscores struct {
   287  			Key1 int64
   288  			Key2 int64
   289  			Key3 int64
   290  		}
   291  	}
   292  	Float struct {
   293  		Fractional struct {
   294  			Key1 float64
   295  			Key2 float64
   296  			Key3 float64
   297  		}
   298  		Exponent struct {
   299  			Key1 float64
   300  			Key2 float64
   301  			Key3 float64
   302  		}
   303  		Both struct {
   304  			Key float64
   305  		}
   306  		Underscores struct {
   307  			Key1 float64
   308  			Key2 float64
   309  		}
   310  	}
   311  	Boolean struct {
   312  		True  bool
   313  		False bool
   314  	}
   315  	Datetime struct {
   316  		Key1 time.Time
   317  		Key2 time.Time
   318  		Key3 time.Time
   319  	}
   320  	Array struct {
   321  		Key1 []int64
   322  		Key2 []string
   323  		Key3 [][]int64
   324  		// TODO: Key4 not supported by go-toml's Unmarshal
   325  		Key4 []interface{}
   326  		Key5 []int64
   327  		Key6 []int64
   328  	}
   329  	Products []struct {
   330  		Name  string
   331  		Sku   int64
   332  		Color string
   333  	}
   334  	Fruit []struct {
   335  		Name     string
   336  		Physical struct {
   337  			Color string
   338  			Shape string
   339  		}
   340  		Variety []struct {
   341  			Name string
   342  		}
   343  	}
   344  }
   345  
   346  func TestUnmarshalReferenceFile(t *testing.T) {
   347  	bytes, err := ioutil.ReadFile("benchmark.toml")
   348  	require.NoError(t, err)
   349  	d := benchmarkDoc{}
   350  	err = toml.Unmarshal(bytes, &d)
   351  	require.NoError(t, err)
   352  
   353  	expected := benchmarkDoc{
   354  		Table: struct {
   355  			Key      string
   356  			Subtable struct{ Key string }
   357  			Inline   struct {
   358  				Name struct {
   359  					First string
   360  					Last  string
   361  				}
   362  				Point struct {
   363  					X int64
   364  					Y int64
   365  				}
   366  			}
   367  		}{
   368  			Key: "value",
   369  			Subtable: struct{ Key string }{
   370  				Key: "another value",
   371  			},
   372  			// note: x.y.z.w is purposefully missing
   373  			Inline: struct {
   374  				Name struct {
   375  					First string
   376  					Last  string
   377  				}
   378  				Point struct {
   379  					X int64
   380  					Y int64
   381  				}
   382  			}{
   383  				Name: struct {
   384  					First string
   385  					Last  string
   386  				}{
   387  					First: "Tom",
   388  					Last:  "Preston-Werner",
   389  				},
   390  				Point: struct {
   391  					X int64
   392  					Y int64
   393  				}{
   394  					X: 1,
   395  					Y: 2,
   396  				},
   397  			},
   398  		},
   399  		String: struct {
   400  			Basic     struct{ Basic string }
   401  			Multiline struct {
   402  				Key1      string
   403  				Key2      string
   404  				Key3      string
   405  				Continued struct {
   406  					Key1 string
   407  					Key2 string
   408  					Key3 string
   409  				}
   410  			}
   411  			Literal struct {
   412  				Winpath   string
   413  				Winpath2  string
   414  				Quoted    string
   415  				Regex     string
   416  				Multiline struct {
   417  					Regex2 string
   418  					Lines  string
   419  				}
   420  			}
   421  		}{
   422  			Basic: struct{ Basic string }{
   423  				Basic: "I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF.",
   424  			},
   425  			Multiline: struct {
   426  				Key1      string
   427  				Key2      string
   428  				Key3      string
   429  				Continued struct {
   430  					Key1 string
   431  					Key2 string
   432  					Key3 string
   433  				}
   434  			}{
   435  				Key1: "One\nTwo",
   436  				Key2: "One\nTwo",
   437  				Key3: "One\nTwo",
   438  
   439  				Continued: struct {
   440  					Key1 string
   441  					Key2 string
   442  					Key3 string
   443  				}{
   444  					Key1: `The quick brown fox jumps over the lazy dog.`,
   445  					Key2: `The quick brown fox jumps over the lazy dog.`,
   446  					Key3: `The quick brown fox jumps over the lazy dog.`,
   447  				},
   448  			},
   449  			Literal: struct {
   450  				Winpath   string
   451  				Winpath2  string
   452  				Quoted    string
   453  				Regex     string
   454  				Multiline struct {
   455  					Regex2 string
   456  					Lines  string
   457  				}
   458  			}{
   459  				Winpath:  `C:\Users\nodejs\templates`,
   460  				Winpath2: `\\ServerX\admin$\system32\`,
   461  				Quoted:   `Tom "Dubs" Preston-Werner`,
   462  				Regex:    `<\i\c*\s*>`,
   463  
   464  				Multiline: struct {
   465  					Regex2 string
   466  					Lines  string
   467  				}{
   468  					Regex2: `I [dw]on't need \d{2} apples`,
   469  					Lines: `The first newline is
   470  trimmed in raw strings.
   471     All other whitespace
   472     is preserved.
   473  `,
   474  				},
   475  			},
   476  		},
   477  		Integer: struct {
   478  			Key1        int64
   479  			Key2        int64
   480  			Key3        int64
   481  			Key4        int64
   482  			Underscores struct {
   483  				Key1 int64
   484  				Key2 int64
   485  				Key3 int64
   486  			}
   487  		}{
   488  			Key1: 99,
   489  			Key2: 42,
   490  			Key3: 0,
   491  			Key4: -17,
   492  
   493  			Underscores: struct {
   494  				Key1 int64
   495  				Key2 int64
   496  				Key3 int64
   497  			}{
   498  				Key1: 1000,
   499  				Key2: 5349221,
   500  				Key3: 12345,
   501  			},
   502  		},
   503  		Float: struct {
   504  			Fractional struct {
   505  				Key1 float64
   506  				Key2 float64
   507  				Key3 float64
   508  			}
   509  			Exponent struct {
   510  				Key1 float64
   511  				Key2 float64
   512  				Key3 float64
   513  			}
   514  			Both        struct{ Key float64 }
   515  			Underscores struct {
   516  				Key1 float64
   517  				Key2 float64
   518  			}
   519  		}{
   520  			Fractional: struct {
   521  				Key1 float64
   522  				Key2 float64
   523  				Key3 float64
   524  			}{
   525  				Key1: 1.0,
   526  				Key2: 3.1415,
   527  				Key3: -0.01,
   528  			},
   529  			Exponent: struct {
   530  				Key1 float64
   531  				Key2 float64
   532  				Key3 float64
   533  			}{
   534  				Key1: 5e+22,
   535  				Key2: 1e6,
   536  				Key3: -2e-2,
   537  			},
   538  			Both: struct{ Key float64 }{
   539  				Key: 6.626e-34,
   540  			},
   541  			Underscores: struct {
   542  				Key1 float64
   543  				Key2 float64
   544  			}{
   545  				Key1: 9224617.445991228313,
   546  				Key2: 1e100,
   547  			},
   548  		},
   549  		Boolean: struct {
   550  			True  bool
   551  			False bool
   552  		}{
   553  			True:  true,
   554  			False: false,
   555  		},
   556  		Datetime: struct {
   557  			Key1 time.Time
   558  			Key2 time.Time
   559  			Key3 time.Time
   560  		}{
   561  			Key1: time.Date(1979, 5, 27, 7, 32, 0, 0, time.UTC),
   562  			Key2: time.Date(1979, 5, 27, 0, 32, 0, 0, time.FixedZone("", -7*3600)),
   563  			Key3: time.Date(1979, 5, 27, 0, 32, 0, 999999000, time.FixedZone("", -7*3600)),
   564  		},
   565  		Array: struct {
   566  			Key1 []int64
   567  			Key2 []string
   568  			Key3 [][]int64
   569  			Key4 []interface{}
   570  			Key5 []int64
   571  			Key6 []int64
   572  		}{
   573  			Key1: []int64{1, 2, 3},
   574  			Key2: []string{"red", "yellow", "green"},
   575  			Key3: [][]int64{{1, 2}, {3, 4, 5}},
   576  			Key4: []interface{}{
   577  				[]interface{}{int64(1), int64(2)},
   578  				[]interface{}{"a", "b", "c"},
   579  			},
   580  			Key5: []int64{1, 2, 3},
   581  			Key6: []int64{1, 2},
   582  		},
   583  		Products: []struct {
   584  			Name  string
   585  			Sku   int64
   586  			Color string
   587  		}{
   588  			{
   589  				Name: "Hammer",
   590  				Sku:  738594937,
   591  			},
   592  			{},
   593  			{
   594  				Name:  "Nail",
   595  				Sku:   284758393,
   596  				Color: "gray",
   597  			},
   598  		},
   599  		Fruit: []struct {
   600  			Name     string
   601  			Physical struct {
   602  				Color string
   603  				Shape string
   604  			}
   605  			Variety []struct{ Name string }
   606  		}{
   607  			{
   608  				Name: "apple",
   609  				Physical: struct {
   610  					Color string
   611  					Shape string
   612  				}{
   613  					Color: "red",
   614  					Shape: "round",
   615  				},
   616  				Variety: []struct{ Name string }{
   617  					{Name: "red delicious"},
   618  					{Name: "granny smith"},
   619  				},
   620  			},
   621  			{
   622  				Name: "banana",
   623  				Variety: []struct{ Name string }{
   624  					{Name: "plantain"},
   625  				},
   626  			},
   627  		},
   628  	}
   629  
   630  	require.Equal(t, expected, d)
   631  }
   632  
   633  var hugoFrontMatterbytes = []byte(`
   634  categories = ["Development", "VIM"]
   635  date = "2012-04-06"
   636  description = "spf13-vim is a cross platform distribution of vim plugins and resources for Vim."
   637  slug = "spf13-vim-3-0-release-and-new-website"
   638  tags = [".vimrc", "plugins", "spf13-vim", "vim"]
   639  title = "spf13-vim 3.0 release and new website"
   640  include_toc = true
   641  show_comments = false
   642  
   643  [[cascade]]
   644    background = "yosemite.jpg"
   645    [cascade._target]
   646      kind = "page"
   647      lang = "en"
   648      path = "/blog/**"
   649  
   650  [[cascade]]
   651    background = "goldenbridge.jpg"
   652    [cascade._target]
   653      kind = "section"
   654  `)
   655  

View as plain text