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 }