Fin/bench/get_test.go

685 lines
15 KiB
Go

package scf_test
import (
"encoding/json"
"strings"
"testing"
config "git.sharkk.net/Go/SCF"
"github.com/BurntSushi/toml"
"gopkg.in/yaml.v3"
)
func BenchmarkRetrieveSimpleValues(b *testing.B) {
configData := `
host "localhost"
port 8080
debug true
timeout 30
`
// Parse once before benchmarking retrieval
reader := strings.NewReader(configData)
cfg, err := config.Load(reader)
if err != nil {
b.Fatalf("Failed to parse config: %v", err)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
// String retrieval
host, err := cfg.GetString("host")
if err != nil || host != "localhost" {
b.Fatalf("Failed to retrieve host: %v", err)
}
// Int retrieval
port, err := cfg.GetInt("port")
if err != nil || port != 8080 {
b.Fatalf("Failed to retrieve port: %v", err)
}
// Bool retrieval
debug, err := cfg.GetBool("debug")
if err != nil || !debug {
b.Fatalf("Failed to retrieve debug: %v", err)
}
// Generic retrieval
timeout, err := cfg.Get("timeout")
if err != nil || timeout.(int) != 30 {
b.Fatalf("Failed to retrieve timeout: %v", err)
}
}
}
func BenchmarkRetrieveNestedValues(b *testing.B) {
configData := `
app {
name "TestApp"
version "1.0.0"
settings {
enableLogging true
maxConnections 100
}
}
database {
host "db.example.com"
port 5432
credentials {
username "admin"
password "secure123"
}
}
`
// Parse once before benchmarking retrieval
reader := strings.NewReader(configData)
cfg, err := config.Load(reader)
if err != nil {
b.Fatalf("Failed to parse config: %v", err)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
// First level nesting
appName, err := cfg.GetString("app.name")
if err != nil || appName != "TestApp" {
b.Fatalf("Failed to retrieve app.name: %v", err)
}
dbPort, err := cfg.GetInt("database.port")
if err != nil || dbPort != 5432 {
b.Fatalf("Failed to retrieve database.port: %v", err)
}
// Second level nesting
logging, err := cfg.GetBool("app.settings.enableLogging")
if err != nil || !logging {
b.Fatalf("Failed to retrieve app.settings.enableLogging: %v", err)
}
username, err := cfg.GetString("database.credentials.username")
if err != nil || username != "admin" {
b.Fatalf("Failed to retrieve database.credentials.username: %v", err)
}
}
}
func BenchmarkRetrieveArrayValues(b *testing.B) {
configData := `
features {
"authentication"
"authorization"
"reporting"
"analytics"
}
numbers {
1
2
3
4
5
}
`
// Parse once before benchmarking retrieval
reader := strings.NewReader(configData)
cfg, err := config.Load(reader)
if err != nil {
b.Fatalf("Failed to parse config: %v", err)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
// Get entire array
features, err := cfg.GetArray("features")
if err != nil || len(features) != 4 {
b.Fatalf("Failed to retrieve features array: %v", err)
}
// Check specific array element
if feature0, ok := features[0].(string); !ok || feature0 != "authentication" {
b.Fatalf("Failed to access array element: %v", features[0])
}
// Get with dot notation for array access
auth, err := cfg.GetString("features.0")
if err != nil || auth != "authentication" {
b.Fatalf("Failed to retrieve features.0: %v", err)
}
// Numeric array
numbers, err := cfg.GetArray("numbers")
if err != nil || len(numbers) != 5 {
b.Fatalf("Failed to retrieve numbers array: %v", err)
}
}
}
func BenchmarkRetrieveMixedValues(b *testing.B) {
configData := `
app {
name "TestApp"
version "1.0.0"
environments {
"development"
"testing"
"production"
}
limits {
requests 1000
connections 100
timeouts {
read 5
write 10
}
}
}
`
// Parse once before benchmarking retrieval
reader := strings.NewReader(configData)
cfg, err := config.Load(reader)
if err != nil {
b.Fatalf("Failed to parse config: %v", err)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
// Simple retrieval
appName, err := cfg.GetString("app.name")
if err != nil || appName != "TestApp" {
b.Fatalf("Failed to retrieve app.name: %v", err)
}
// Array retrieval
environments, err := cfg.GetArray("app.environments")
if err != nil || len(environments) != 3 {
b.Fatalf("Failed to retrieve app.environments: %v", err)
}
// Deeply nested value
readTimeout, err := cfg.GetInt("app.limits.timeouts.read")
if err != nil || readTimeout != 5 {
b.Fatalf("Failed to retrieve app.limits.timeouts.read: %v", err)
}
// Array item with dot notation
prod, err := cfg.GetString("app.environments.2")
if err != nil || prod != "production" {
b.Fatalf("Failed to retrieve app.environments.2: %v", err)
}
}
}
// Value Retrieval Benchmarks for JSON
func BenchmarkRetrieveSimpleValuesJSON(b *testing.B) {
configData := `{
"host": "localhost",
"port": 8080,
"debug": true,
"timeout": 30
}`
// Parse once before benchmarking retrieval
var result map[string]any
err := json.Unmarshal([]byte(configData), &result)
if err != nil {
b.Fatalf("Failed to parse JSON: %v", err)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
// String retrieval
host, ok := result["host"].(string)
if !ok || host != "localhost" {
b.Fatalf("Failed to retrieve host")
}
// Number retrieval
port, ok := result["port"].(float64)
if !ok || port != 8080 {
b.Fatalf("Failed to retrieve port")
}
// Boolean retrieval
debug, ok := result["debug"].(bool)
if !ok || !debug {
b.Fatalf("Failed to retrieve debug")
}
// Generic retrieval
timeout := result["timeout"]
if timeout.(float64) != 30 {
b.Fatalf("Failed to retrieve timeout")
}
}
}
func BenchmarkRetrieveNestedValuesJSON(b *testing.B) {
configData := `{
"app": {
"name": "TestApp",
"version": "1.0.0",
"settings": {
"enableLogging": true,
"maxConnections": 100
}
},
"database": {
"host": "db.example.com",
"port": 5432,
"credentials": {
"username": "admin",
"password": "secure123"
}
}
}`
// Parse once before benchmarking retrieval
var result map[string]any
err := json.Unmarshal([]byte(configData), &result)
if err != nil {
b.Fatalf("Failed to parse JSON: %v", err)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
// First level nesting
app, ok := result["app"].(map[string]any)
if !ok {
b.Fatalf("Failed to retrieve app")
}
appName, ok := app["name"].(string)
if !ok || appName != "TestApp" {
b.Fatalf("Failed to retrieve app.name")
}
database, ok := result["database"].(map[string]any)
if !ok {
b.Fatalf("Failed to retrieve database")
}
dbPort, ok := database["port"].(float64)
if !ok || dbPort != 5432 {
b.Fatalf("Failed to retrieve database.port")
}
// Second level nesting
settings, ok := app["settings"].(map[string]any)
if !ok {
b.Fatalf("Failed to retrieve app.settings")
}
logging, ok := settings["enableLogging"].(bool)
if !ok || !logging {
b.Fatalf("Failed to retrieve app.settings.enableLogging")
}
credentials, ok := database["credentials"].(map[string]any)
if !ok {
b.Fatalf("Failed to retrieve database.credentials")
}
username, ok := credentials["username"].(string)
if !ok || username != "admin" {
b.Fatalf("Failed to retrieve database.credentials.username")
}
}
}
func BenchmarkRetrieveArrayValuesJSON(b *testing.B) {
configData := `{
"features": [
"authentication",
"authorization",
"reporting",
"analytics"
],
"numbers": [1, 2, 3, 4, 5]
}`
// Parse once before benchmarking retrieval
var result map[string]any
err := json.Unmarshal([]byte(configData), &result)
if err != nil {
b.Fatalf("Failed to parse JSON: %v", err)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
// Get entire array
features, ok := result["features"].([]any)
if !ok || len(features) != 4 {
b.Fatalf("Failed to retrieve features array")
}
// Check specific array element
if feature0, ok := features[0].(string); !ok || feature0 != "authentication" {
b.Fatalf("Failed to access array element")
}
// Numeric array
numbers, ok := result["numbers"].([]any)
if !ok || len(numbers) != 5 {
b.Fatalf("Failed to retrieve numbers array")
}
}
}
// Value Retrieval Benchmarks for YAML
func BenchmarkRetrieveSimpleValuesYAML(b *testing.B) {
configData := `
host: localhost
port: 8080
debug: true
timeout: 30
`
// Parse once before benchmarking retrieval
var result map[string]any
err := yaml.Unmarshal([]byte(configData), &result)
if err != nil {
b.Fatalf("Failed to parse YAML: %v", err)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
// String retrieval
host, ok := result["host"].(string)
if !ok || host != "localhost" {
b.Fatalf("Failed to retrieve host")
}
// Number retrieval
port, ok := result["port"].(int)
if !ok || port != 8080 {
b.Fatalf("Failed to retrieve port")
}
// Boolean retrieval
debug, ok := result["debug"].(bool)
if !ok || !debug {
b.Fatalf("Failed to retrieve debug")
}
// Generic retrieval
timeout := result["timeout"]
if timeout.(int) != 30 {
b.Fatalf("Failed to retrieve timeout")
}
}
}
// Value Retrieval Benchmarks for TOML
func BenchmarkRetrieveSimpleValuesTOML(b *testing.B) {
configData := `
host = "localhost"
port = 8080
debug = true
timeout = 30
`
// Parse once before benchmarking retrieval
var result map[string]any
err := toml.Unmarshal([]byte(configData), &result)
if err != nil {
b.Fatalf("Failed to parse TOML: %v", err)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
// String retrieval
host, ok := result["host"].(string)
if !ok || host != "localhost" {
b.Fatalf("Failed to retrieve host")
}
// Number retrieval
port, ok := result["port"].(int64)
if !ok || port != 8080 {
b.Fatalf("Failed to retrieve port")
}
// Boolean retrieval
debug, ok := result["debug"].(bool)
if !ok || !debug {
b.Fatalf("Failed to retrieve debug")
}
// Generic retrieval
timeout := result["timeout"]
if timeout.(int64) != 30 {
b.Fatalf("Failed to retrieve timeout")
}
}
}
// Comprehensive value retrieval comparison benchmark
func BenchmarkComplexValueRetrieval(b *testing.B) {
// Setup complex config with deep nesting and arrays for all formats
customConfig := `
app {
name "TestApp"
version "1.0.0"
settings {
enableLogging true
maxConnections 100
timeouts {
read 5
write 10
}
}
environments {
"development"
"testing"
"production"
}
}
`
jsonConfig := `{
"app": {
"name": "TestApp",
"version": "1.0.0",
"settings": {
"enableLogging": true,
"maxConnections": 100,
"timeouts": {
"read": 5,
"write": 10
}
},
"environments": [
"development",
"testing",
"production"
]
}
}`
yamlConfig := `
app:
name: TestApp
version: 1.0.0
settings:
enableLogging: true
maxConnections: 100
timeouts:
read: 5
write: 10
environments:
- development
- testing
- production
`
tomlConfig := `
[app]
name = "TestApp"
version = "1.0.0"
environments = ["development", "testing", "production"]
[app.settings]
enableLogging = true
maxConnections = 100
[app.settings.timeouts]
read = 5
write = 10
`
// Parse configs once before benchmarking
// Custom config
customReader := strings.NewReader(customConfig)
customCfg, err := config.Load(customReader)
if err != nil {
b.Fatalf("Failed to parse custom config: %v", err)
}
// JSON config
var jsonResult map[string]any
err = json.Unmarshal([]byte(jsonConfig), &jsonResult)
if err != nil {
b.Fatalf("Failed to parse JSON: %v", err)
}
// YAML config
var yamlResult map[string]any
err = yaml.Unmarshal([]byte(yamlConfig), &yamlResult)
if err != nil {
b.Fatalf("Failed to parse YAML: %v", err)
}
// TOML config
var tomlResult map[string]any
err = toml.Unmarshal([]byte(tomlConfig), &tomlResult)
if err != nil {
b.Fatalf("Failed to parse TOML: %v", err)
}
directData := customCfg.GetData()
b.Run("Custom-SimpleGet", func(b *testing.B) {
for i := 0; i < b.N; i++ {
_, err := customCfg.GetString("app.name")
if err != nil {
b.Fatalf("Failed to retrieve app.name: %v", err)
}
}
})
b.Run("Custom-DeepGet", func(b *testing.B) {
for i := 0; i < b.N; i++ {
_, err := customCfg.GetInt("app.settings.timeouts.read")
if err != nil {
b.Fatalf("Failed to retrieve app.settings.timeouts.read: %v", err)
}
}
})
b.Run("Custom-ArrayGet", func(b *testing.B) {
for i := 0; i < b.N; i++ {
_, err := customCfg.GetString("app.environments.1")
if err != nil {
b.Fatalf("Failed to retrieve app.environments.1: %v", err)
}
}
})
b.Run("Direct-SimpleGet", func(b *testing.B) {
for i := 0; i < b.N; i++ {
app := directData["app"].(map[string]any)
_ = app["name"].(string)
}
})
b.Run("Direct-DeepGet", func(b *testing.B) {
for i := 0; i < b.N; i++ {
app := directData["app"].(map[string]any)
settings := app["settings"].(map[string]any)
timeouts := settings["timeouts"].(map[string]any)
_ = timeouts["read"].(int)
}
})
b.Run("Direct-ArrayGet", func(b *testing.B) {
for i := 0; i < b.N; i++ {
app := directData["app"].(map[string]any)
environments := app["environments"].([]any)
_ = environments[1].(string)
}
})
b.Run("JSON-SimpleGet", func(b *testing.B) {
for i := 0; i < b.N; i++ {
app := jsonResult["app"].(map[string]any)
_ = app["name"].(string)
}
})
b.Run("JSON-DeepGet", func(b *testing.B) {
for i := 0; i < b.N; i++ {
app := jsonResult["app"].(map[string]any)
settings := app["settings"].(map[string]any)
timeouts := settings["timeouts"].(map[string]any)
_ = timeouts["read"].(float64)
}
})
b.Run("JSON-ArrayGet", func(b *testing.B) {
for i := 0; i < b.N; i++ {
app := jsonResult["app"].(map[string]any)
environments := app["environments"].([]any)
_ = environments[1].(string)
}
})
b.Run("YAML-SimpleGet", func(b *testing.B) {
for i := 0; i < b.N; i++ {
app := yamlResult["app"].(map[string]any)
_ = app["name"].(string)
}
})
b.Run("YAML-DeepGet", func(b *testing.B) {
for i := 0; i < b.N; i++ {
app := yamlResult["app"].(map[string]any)
settings := app["settings"].(map[string]any)
timeouts := settings["timeouts"].(map[string]any)
_ = timeouts["read"].(int)
}
})
b.Run("YAML-ArrayGet", func(b *testing.B) {
for i := 0; i < b.N; i++ {
app := yamlResult["app"].(map[string]any)
environments := app["environments"].([]any)
_ = environments[1].(string)
}
})
b.Run("TOML-SimpleGet", func(b *testing.B) {
for i := 0; i < b.N; i++ {
app := tomlResult["app"].(map[string]any)
_ = app["name"].(string)
}
})
b.Run("TOML-DeepGet", func(b *testing.B) {
for i := 0; i < b.N; i++ {
app := tomlResult["app"].(map[string]any)
settings := app["settings"].(map[string]any)
timeouts := settings["timeouts"].(map[string]any)
_ = timeouts["read"].(int64)
}
})
b.Run("TOML-ArrayGet", func(b *testing.B) {
for i := 0; i < b.N; i++ {
app := tomlResult["app"].(map[string]any)
environments := app["environments"].([]any)
_ = environments[1].(string)
}
})
}