diff --git a/bench_test.go b/bench_test.go new file mode 100644 index 0000000..0504c37 --- /dev/null +++ b/bench_test.go @@ -0,0 +1,129 @@ +// Copyright (c) 2026 Petr BalvĂ­n (https://petrbalvin.org) +// SPDX-License-Identifier: MIT + +package interpres + +import ( + "fmt" + "strings" + "testing" + "time" +) + +// benchDoc is a representative configuration document: every scalar kind, an +// inline table, sub-tables, and an array of tables. +var benchDoc = []byte(`title = "benchmark configuration" +replicas = 3 +ratio = 0.75 +enabled = true +when = 2026-09-17T12:00:00Z +local = 2026-09-17T12:00:00 +tags = ["alpha", "beta", "gamma"] +limits = { cpu = 4, memory = 1024 } + +[server] +host = "localhost" +port = 8080 +hosts = ["a.example", "b.example"] + +[server.tls] +enabled = true +cert = "/etc/cert.pem" + +[[items]] +name = "first" +weight = 10 +flags = ["x", "y"] + +[[items]] +name = "second" +weight = 20 +flags = ["z"] +`) + +// longDoc is generated once so the large-input benchmarks measure parsing, +// not document construction. Roughly 2000 array-of-tables entries. +var longDoc = func() []byte { + var b strings.Builder + b.WriteString("title = \"long\"\n") + for i := range 2000 { + fmt.Fprintf(&b, "[[entry]]\nname = \"entry-%d\"\nweight = %d\nwhen = 2026-09-17T12:00:00Z\nratio = 0.5\ntags = [\"a\", \"b\", \"c\"]\n\n", i, i) + } + return []byte(b.String()) +}() + +type benchTLS struct { + Enabled bool `toml:"enabled"` + Cert string `toml:"cert"` +} + +type benchServer struct { + Host string `toml:"host"` + Port int `toml:"port"` + Hosts []string `toml:"hosts"` + TLS benchTLS `toml:"tls"` +} + +type benchItem struct { + Name string `toml:"name"` + Weight int `toml:"weight"` + Flags []string `toml:"flags"` +} + +type benchConfig struct { + Title string `toml:"title"` + Replicas int `toml:"replicas"` + Ratio float64 `toml:"ratio"` + Enabled bool `toml:"enabled"` + When time.Time `toml:"when"` + Local LocalDateTime `toml:"local"` + Tags []string `toml:"tags"` + Limits map[string]any `toml:"limits"` + Server benchServer `toml:"server"` + Items []benchItem `toml:"items"` +} + +func BenchmarkParse(b *testing.B) { + b.ReportAllocs() + b.SetBytes(int64(len(benchDoc))) + for b.Loop() { + if _, err := Parse(benchDoc); err != nil { + b.Fatal(err) + } + } +} + +func BenchmarkMarshal(b *testing.B) { + tree, err := Parse(benchDoc) + if err != nil { + b.Fatal(err) + } + b.ReportAllocs() + b.SetBytes(int64(len(benchDoc))) + for b.Loop() { + if _, err := Marshal(tree); err != nil { + b.Fatal(err) + } + } +} + +func BenchmarkStrictDecode(b *testing.B) { + dec := NewDecoder().DisallowUnknownFields() + b.ReportAllocs() + for b.Loop() { + var cfg benchConfig + if err := dec.Decode(benchDoc, &cfg); err != nil { + b.Fatal(err) + } + } +} + +func BenchmarkParseLong(b *testing.B) { + b.ReportAllocs() + b.SetBytes(int64(len(longDoc))) + for b.Loop() { + if _, err := Parse(longDoc); err != nil { + b.Fatal(err) + } + } +}