git.sr.ht/~pingoo/stdx@v0.0.0-20240218134121-094174641f6e/toml/bench_test.go (about)

     1  //go:build go1.16
     2  // +build go1.16
     3  
     4  package toml_test
     5  
     6  import (
     7  	"bytes"
     8  	"io/fs"
     9  	"io/ioutil"
    10  	"path/filepath"
    11  	"sort"
    12  	"strings"
    13  	"testing"
    14  	"time"
    15  
    16  	"git.sr.ht/~pingoo/stdx/toml"
    17  	tomltest "git.sr.ht/~pingoo/stdx/toml/internal/toml-test"
    18  )
    19  
    20  func BenchmarkDecode(b *testing.B) {
    21  	files := make(map[string][]string)
    22  	fs.WalkDir(tomltest.EmbeddedTests(), ".", func(path string, d fs.DirEntry, err error) error {
    23  		if strings.HasPrefix(path, "valid/") && strings.HasSuffix(path, ".toml") {
    24  			d, _ := fs.ReadFile(tomltest.EmbeddedTests(), path)
    25  			g := filepath.Dir(path[6:])
    26  			if g == "." {
    27  				g = "top"
    28  			}
    29  			files[g] = append(files[g], string(d))
    30  		}
    31  		return nil
    32  	})
    33  
    34  	type test struct {
    35  		group string
    36  		toml  []string
    37  	}
    38  	tests := make([]test, 0, len(files))
    39  	for k, v := range files {
    40  		tests = append(tests, test{group: k, toml: v})
    41  	}
    42  	sort.Slice(tests, func(i, j int) bool { return tests[i].group < tests[j].group })
    43  
    44  	b.ResetTimer()
    45  	for _, tt := range tests {
    46  		b.Run(tt.group, func(b *testing.B) {
    47  			b.ResetTimer()
    48  			for n := 0; n < b.N; n++ {
    49  				for _, f := range tt.toml {
    50  					var val map[string]interface{}
    51  					toml.Decode(f, &val)
    52  				}
    53  			}
    54  		})
    55  	}
    56  }
    57  
    58  func BenchmarkEncode(b *testing.B) {
    59  	files := make(map[string][]map[string]interface{})
    60  	fs.WalkDir(tomltest.EmbeddedTests(), ".", func(path string, d fs.DirEntry, err error) error {
    61  		if strings.HasPrefix(path, "valid/") && strings.HasSuffix(path, ".toml") {
    62  			d, _ := fs.ReadFile(tomltest.EmbeddedTests(), path)
    63  			g := filepath.Dir(path[6:])
    64  			if g == "." {
    65  				g = "top"
    66  			}
    67  
    68  			// "next" version of TOML.
    69  			if path == "valid/string/escape-esc.toml" {
    70  				return nil
    71  			}
    72  
    73  			var dec map[string]interface{}
    74  			_, err := toml.Decode(string(d), &dec)
    75  			if err != nil {
    76  				b.Fatalf("decode %q: %s", path, err)
    77  			}
    78  
    79  			buf := new(bytes.Buffer)
    80  			err = toml.NewEncoder(buf).Encode(dec)
    81  			if err != nil {
    82  				b.Logf("encode failed for %q (skipping): %s", path, err)
    83  				return nil
    84  			}
    85  
    86  			files[g] = append(files[g], dec)
    87  		}
    88  		return nil
    89  	})
    90  
    91  	type test struct {
    92  		group string
    93  		data  []map[string]interface{}
    94  	}
    95  	tests := make([]test, 0, len(files))
    96  	for k, v := range files {
    97  		tests = append(tests, test{group: k, data: v})
    98  	}
    99  	sort.Slice(tests, func(i, j int) bool { return tests[i].group < tests[j].group })
   100  
   101  	b.ResetTimer()
   102  	for _, tt := range tests {
   103  		b.Run(tt.group, func(b *testing.B) {
   104  			buf := new(bytes.Buffer)
   105  			buf.Grow(1024 * 64)
   106  			b.ResetTimer()
   107  			for n := 0; n < b.N; n++ {
   108  				for _, f := range tt.data {
   109  					toml.NewEncoder(buf).Encode(f)
   110  				}
   111  			}
   112  		})
   113  	}
   114  }
   115  
   116  func BenchmarkExample(b *testing.B) {
   117  	d, err := ioutil.ReadFile("_example/example.toml")
   118  	if err != nil {
   119  		b.Fatal(err)
   120  	}
   121  	t := string(d)
   122  
   123  	var decoded example
   124  	_, err = toml.Decode(t, &decoded)
   125  	if err != nil {
   126  		b.Fatal(err)
   127  	}
   128  
   129  	buf := new(bytes.Buffer)
   130  	err = toml.NewEncoder(buf).Encode(decoded)
   131  	if err != nil {
   132  		b.Fatal(err)
   133  	}
   134  
   135  	b.ResetTimer()
   136  	b.Run("decode", func(b *testing.B) {
   137  		for n := 0; n < b.N; n++ {
   138  			var c example
   139  			toml.Decode(t, &c)
   140  		}
   141  	})
   142  
   143  	b.Run("encode", func(b *testing.B) {
   144  		for n := 0; n < b.N; n++ {
   145  			buf.Reset()
   146  			toml.NewEncoder(buf).Encode(decoded)
   147  		}
   148  	})
   149  }
   150  
   151  // Copy from _example/example.go
   152  type (
   153  	example struct {
   154  		Title      string
   155  		Integers   []int
   156  		Times      []fmtTime
   157  		Duration   []duration
   158  		Distros    []distro
   159  		Servers    map[string]server
   160  		Characters map[string][]struct {
   161  			Name string
   162  			Rank string
   163  		}
   164  	}
   165  
   166  	server struct {
   167  		IP       string
   168  		Hostname string
   169  		Enabled  bool
   170  	}
   171  
   172  	distro struct {
   173  		Name     string
   174  		Packages string
   175  	}
   176  
   177  	duration struct{ time.Duration }
   178  	fmtTime  struct{ time.Time }
   179  )
   180  
   181  func (d *duration) UnmarshalText(text []byte) (err error) {
   182  	d.Duration, err = time.ParseDuration(string(text))
   183  	return err
   184  }
   185  
   186  func (t fmtTime) String() string {
   187  	f := "2006-01-02 15:04:05.999999999"
   188  	if t.Time.Hour() == 0 {
   189  		f = "2006-01-02"
   190  	}
   191  	if t.Time.Year() == 0 {
   192  		f = "15:04:05.999999999"
   193  	}
   194  	if t.Time.Location() == time.UTC {
   195  		f += " UTC"
   196  	} else {
   197  		f += " -0700"
   198  	}
   199  	return t.Time.Format(`"` + f + `"`)
   200  }