From b334b09efad73faef1fbd5b13e4dbdbefbfcfb6d Mon Sep 17 00:00:00 2001 From: Sky Johnson Date: Tue, 4 Mar 2025 18:23:09 -0600 Subject: [PATCH] ref 9 --- bench/{bench_test.go => get_test.go} | 607 -------------------------- bench/parse_test.go | 617 +++++++++++++++++++++++++++ pool.go | 12 +- scanner.go | 4 +- 4 files changed, 625 insertions(+), 615 deletions(-) rename bench/{bench_test.go => get_test.go} (56%) create mode 100644 bench/parse_test.go diff --git a/bench/bench_test.go b/bench/get_test.go similarity index 56% rename from bench/bench_test.go rename to bench/get_test.go index 4a3bfdf..c16d4be 100644 --- a/bench/bench_test.go +++ b/bench/get_test.go @@ -2,7 +2,6 @@ package config import ( "encoding/json" - "strconv" "strings" "testing" @@ -11,612 +10,6 @@ import ( "gopkg.in/yaml.v3" ) -// Original benchmarks -func BenchmarkSmallConfig(b *testing.B) { - // Small config with just a few key-value pairs - smallConfig := ` - host "localhost" - port 8080 - debug true - timeout 30 - ` - - b.ResetTimer() - for i := 0; i < b.N; i++ { - reader := strings.NewReader(smallConfig) - _, err := config.Load(reader) - if err != nil { - b.Fatalf("Failed to parse small config: %v", err) - } - } -} - -func BenchmarkMediumConfig(b *testing.B) { - // Medium config with nested structures and arrays - mediumConfig := ` - app { - name "TestApp" - version "1.0.0" - enableLogging true - } - - database { - host "db.example.com" - port 5432 - credentials { - username "admin" - password "secure123" - } - } - - features { - "authentication" - "authorization" - "reporting" - "analytics" - } - - timeouts { - connect 5 - read 10 - write 10 - idle 60 - } - - -- Comments to add some parsing overhead - endpoints { - api "/api/v1" - web "/web" - admin "/admin" - health "/health" - } - ` - - b.ResetTimer() - for i := 0; i < b.N; i++ { - reader := strings.NewReader(mediumConfig) - _, err := config.Load(reader) - if err != nil { - b.Fatalf("Failed to parse medium config: %v", err) - } - } -} - -func BenchmarkLargeConfig(b *testing.B) { - // Simpler large config with careful bracket matching - largeConfig := ` - application { - name "EnterpriseApp" - version "2.5.1" - environment "production" - debug false - maxConnections 1000 - timeout 30 - retryCount 3 - logLevel "info" - } - - -- Database cluster configuration - databases { - primary { - host "primary-db.example.com" - port 5432 - maxConnections 100 - credentials { - username "app_user" - password "super_secret" - ssl true - timeout 5 - } - } - - replica { - host "replica-db.example.com" - port 5432 - maxConnections 200 - credentials { - username "read_user" - password "read_only_pw" - ssl true - } - } - } - - allowedIPs { - "192.168.1.1" - "192.168.1.2" - "192.168.1.3" - "192.168.1.4" - "192.168.1.5" - } - - -- Add 50 numbered settings to make the config large - settings {` - - // Add many numbered settings - var builder strings.Builder - builder.WriteString(largeConfig) - - for i := 1; i <= 50; i++ { - builder.WriteString("\n\t\tsetting") - builder.WriteString(strconv.Itoa(i)) - builder.WriteString(" ") - builder.WriteString(strconv.Itoa(i * 10)) - } - - // Close the settings block and add one more block - builder.WriteString(` - } - - roles { - admin { - permissions { - "read" - "write" - "delete" - "admin" - } - } - user { - permissions { - "read" - "write" - } - } - } - `) - - largeConfig = builder.String() - - b.ResetTimer() - for i := 0; i < b.N; i++ { - reader := strings.NewReader(largeConfig) - _, err := config.Load(reader) - if err != nil { - b.Fatalf("Failed to parse large config: %v", err) - } - } -} - -// JSON Benchmarks -func BenchmarkSmallConfigJSON(b *testing.B) { - smallConfigJSON := `{ - "host": "localhost", - "port": 8080, - "debug": true, - "timeout": 30 - }` - - b.ResetTimer() - for i := 0; i < b.N; i++ { - reader := strings.NewReader(smallConfigJSON) - var result map[string]interface{} - decoder := json.NewDecoder(reader) - err := decoder.Decode(&result) - if err != nil { - b.Fatalf("Failed to parse small JSON config: %v", err) - } - } -} - -func BenchmarkMediumConfigJSON(b *testing.B) { - mediumConfigJSON := `{ - "app": { - "name": "TestApp", - "version": "1.0.0", - "enableLogging": true - }, - "database": { - "host": "db.example.com", - "port": 5432, - "credentials": { - "username": "admin", - "password": "secure123" - } - }, - "features": [ - "authentication", - "authorization", - "reporting", - "analytics" - ], - "timeouts": { - "connect": 5, - "read": 10, - "write": 10, - "idle": 60 - }, - "endpoints": { - "api": "/api/v1", - "web": "/web", - "admin": "/admin", - "health": "/health" - } - }` - - b.ResetTimer() - for i := 0; i < b.N; i++ { - reader := strings.NewReader(mediumConfigJSON) - var result map[string]interface{} - decoder := json.NewDecoder(reader) - err := decoder.Decode(&result) - if err != nil { - b.Fatalf("Failed to parse medium JSON config: %v", err) - } - } -} - -func BenchmarkLargeConfigJSON(b *testing.B) { - // Start building the large JSON config - largeConfigJSON := `{ - "application": { - "name": "EnterpriseApp", - "version": "2.5.1", - "environment": "production", - "debug": false, - "maxConnections": 1000, - "timeout": 30, - "retryCount": 3, - "logLevel": "info" - }, - "databases": { - "primary": { - "host": "primary-db.example.com", - "port": 5432, - "maxConnections": 100, - "credentials": { - "username": "app_user", - "password": "super_secret", - "ssl": true, - "timeout": 5 - } - }, - "replica": { - "host": "replica-db.example.com", - "port": 5432, - "maxConnections": 200, - "credentials": { - "username": "read_user", - "password": "read_only_pw", - "ssl": true - } - } - }, - "allowedIPs": [ - "192.168.1.1", - "192.168.1.2", - "192.168.1.3", - "192.168.1.4", - "192.168.1.5" - ], - "settings": {` - - var builder strings.Builder - builder.WriteString(largeConfigJSON) - - // Add many numbered settings - for i := 1; i <= 50; i++ { - if i > 1 { - builder.WriteString(",") - } - builder.WriteString("\n\t\t\t\"setting") - builder.WriteString(strconv.Itoa(i)) - builder.WriteString("\": ") - builder.WriteString(strconv.Itoa(i * 10)) - } - - // Close the settings block and add roles - builder.WriteString(` - }, - "roles": { - "admin": { - "permissions": [ - "read", - "write", - "delete", - "admin" - ] - }, - "user": { - "permissions": [ - "read", - "write" - ] - } - } - }`) - - largeConfigJSONString := builder.String() - - b.ResetTimer() - for i := 0; i < b.N; i++ { - reader := strings.NewReader(largeConfigJSONString) - var result map[string]interface{} - decoder := json.NewDecoder(reader) - err := decoder.Decode(&result) - if err != nil { - b.Fatalf("Failed to parse large JSON config: %v", err) - } - } -} - -// YAML Benchmarks -func BenchmarkSmallConfigYAML(b *testing.B) { - smallConfigYAML := ` -host: localhost -port: 8080 -debug: true -timeout: 30 -` - - b.ResetTimer() - for i := 0; i < b.N; i++ { - var result map[string]interface{} - err := yaml.Unmarshal([]byte(smallConfigYAML), &result) - if err != nil { - b.Fatalf("Failed to parse small YAML config: %v", err) - } - } -} - -func BenchmarkMediumConfigYAML(b *testing.B) { - mediumConfigYAML := ` -app: - name: TestApp - version: 1.0.0 - enableLogging: true -database: - host: db.example.com - port: 5432 - credentials: - username: admin - password: secure123 -features: - - authentication - - authorization - - reporting - - analytics -timeouts: - connect: 5 - read: 10 - write: 10 - idle: 60 -# Comments to add some parsing overhead -endpoints: - api: /api/v1 - web: /web - admin: /admin - health: /health -` - - b.ResetTimer() - for i := 0; i < b.N; i++ { - var result map[string]interface{} - err := yaml.Unmarshal([]byte(mediumConfigYAML), &result) - if err != nil { - b.Fatalf("Failed to parse medium YAML config: %v", err) - } - } -} - -func BenchmarkLargeConfigYAML(b *testing.B) { - // Start building the large YAML config - largeConfigYAML := ` -application: - name: EnterpriseApp - version: 2.5.1 - environment: production - debug: false - maxConnections: 1000 - timeout: 30 - retryCount: 3 - logLevel: info - -# Database cluster configuration -databases: - primary: - host: primary-db.example.com - port: 5432 - maxConnections: 100 - credentials: - username: app_user - password: super_secret - ssl: true - timeout: 5 - replica: - host: replica-db.example.com - port: 5432 - maxConnections: 200 - credentials: - username: read_user - password: read_only_pw - ssl: true - -allowedIPs: - - 192.168.1.1 - - 192.168.1.2 - - 192.168.1.3 - - 192.168.1.4 - - 192.168.1.5 - -# Add 50 numbered settings to make the config large -settings: -` - - var builder strings.Builder - builder.WriteString(largeConfigYAML) - - // Add many numbered settings - for i := 1; i <= 50; i++ { - builder.WriteString(" setting") - builder.WriteString(strconv.Itoa(i)) - builder.WriteString(": ") - builder.WriteString(strconv.Itoa(i * 10)) - builder.WriteString("\n") - } - - // Add roles - builder.WriteString(` -roles: - admin: - permissions: - - read - - write - - delete - - admin - user: - permissions: - - read - - write -`) - - largeConfigYAMLString := builder.String() - - b.ResetTimer() - for i := 0; i < b.N; i++ { - var result map[string]interface{} - err := yaml.Unmarshal([]byte(largeConfigYAMLString), &result) - if err != nil { - b.Fatalf("Failed to parse large YAML config: %v", err) - } - } -} - -// TOML Benchmarks -func BenchmarkSmallConfigTOML(b *testing.B) { - smallConfigTOML := ` -host = "localhost" -port = 8080 -debug = true -timeout = 30 -` - - b.ResetTimer() - for i := 0; i < b.N; i++ { - var result map[string]interface{} - err := toml.Unmarshal([]byte(smallConfigTOML), &result) - if err != nil { - b.Fatalf("Failed to parse small TOML config: %v", err) - } - } -} - -func BenchmarkMediumConfigTOML(b *testing.B) { - mediumConfigTOML := ` -[app] -name = "TestApp" -version = "1.0.0" -enableLogging = true - -[database] -host = "db.example.com" -port = 5432 - -[database.credentials] -username = "admin" -password = "secure123" - -features = ["authentication", "authorization", "reporting", "analytics"] - -[timeouts] -connect = 5 -read = 10 -write = 10 -idle = 60 - -# Comments to add some parsing overhead -[endpoints] -api = "/api/v1" -web = "/web" -admin = "/admin" -health = "/health" -` - - b.ResetTimer() - for i := 0; i < b.N; i++ { - var result map[string]interface{} - err := toml.Unmarshal([]byte(mediumConfigTOML), &result) - if err != nil { - b.Fatalf("Failed to parse medium TOML config: %v", err) - } - } -} - -func BenchmarkLargeConfigTOML(b *testing.B) { - // Start building the large TOML config - largeConfigTOML := ` -[application] -name = "EnterpriseApp" -version = "2.5.1" -environment = "production" -debug = false -maxConnections = 1000 -timeout = 30 -retryCount = 3 -logLevel = "info" - -# Database cluster configuration -[databases.primary] -host = "primary-db.example.com" -port = 5432 -maxConnections = 100 - -[databases.primary.credentials] -username = "app_user" -password = "super_secret" -ssl = true -timeout = 5 - -[databases.replica] -host = "replica-db.example.com" -port = 5432 -maxConnections = 200 - -[databases.replica.credentials] -username = "read_user" -password = "read_only_pw" -ssl = true - -allowedIPs = ["192.168.1.1", "192.168.1.2", "192.168.1.3", "192.168.1.4", "192.168.1.5"] - -# Add 50 numbered settings to make the config large -[settings] -` - - var builder strings.Builder - builder.WriteString(largeConfigTOML) - - // Add many numbered settings - for i := 1; i <= 50; i++ { - builder.WriteString("setting") - builder.WriteString(strconv.Itoa(i)) - builder.WriteString(" = ") - builder.WriteString(strconv.Itoa(i * 10)) - builder.WriteString("\n") - } - - // Add roles - builder.WriteString(` -[roles.admin] -permissions = ["read", "write", "delete", "admin"] - -[roles.user] -permissions = ["read", "write"] -`) - - largeConfigTOMLString := builder.String() - - b.ResetTimer() - for i := 0; i < b.N; i++ { - var result map[string]interface{} - err := toml.Unmarshal([]byte(largeConfigTOMLString), &result) - if err != nil { - b.Fatalf("Failed to parse large TOML config: %v", err) - } - } -} - -// Value Retrieval Benchmarks for Custom Config Format func BenchmarkRetrieveSimpleValues(b *testing.B) { configData := ` host "localhost" diff --git a/bench/parse_test.go b/bench/parse_test.go new file mode 100644 index 0000000..76873ad --- /dev/null +++ b/bench/parse_test.go @@ -0,0 +1,617 @@ +package config + +import ( + "encoding/json" + "strconv" + "strings" + "testing" + + config "git.sharkk.net/Go/Config" + "github.com/BurntSushi/toml" + "gopkg.in/yaml.v3" +) + +// Original benchmarks +func BenchmarkSmallConfig(b *testing.B) { + // Small config with just a few key-value pairs + smallConfig := ` + host "localhost" + port 8080 + debug true + timeout 30 + ` + + b.ResetTimer() + for i := 0; i < b.N; i++ { + reader := strings.NewReader(smallConfig) + _, err := config.Load(reader) + if err != nil { + b.Fatalf("Failed to parse small config: %v", err) + } + } +} + +func BenchmarkMediumConfig(b *testing.B) { + // Medium config with nested structures and arrays + mediumConfig := ` + app { + name "TestApp" + version "1.0.0" + enableLogging true + } + + database { + host "db.example.com" + port 5432 + credentials { + username "admin" + password "secure123" + } + } + + features { + "authentication" + "authorization" + "reporting" + "analytics" + } + + timeouts { + connect 5 + read 10 + write 10 + idle 60 + } + + -- Comments to add some parsing overhead + endpoints { + api "/api/v1" + web "/web" + admin "/admin" + health "/health" + } + ` + + b.ResetTimer() + for i := 0; i < b.N; i++ { + reader := strings.NewReader(mediumConfig) + _, err := config.Load(reader) + if err != nil { + b.Fatalf("Failed to parse medium config: %v", err) + } + } +} + +func BenchmarkLargeConfig(b *testing.B) { + // Simpler large config with careful bracket matching + largeConfig := ` + application { + name "EnterpriseApp" + version "2.5.1" + environment "production" + debug false + maxConnections 1000 + timeout 30 + retryCount 3 + logLevel "info" + } + + -- Database cluster configuration + databases { + primary { + host "primary-db.example.com" + port 5432 + maxConnections 100 + credentials { + username "app_user" + password "super_secret" + ssl true + timeout 5 + } + } + + replica { + host "replica-db.example.com" + port 5432 + maxConnections 200 + credentials { + username "read_user" + password "read_only_pw" + ssl true + } + } + } + + allowedIPs { + "192.168.1.1" + "192.168.1.2" + "192.168.1.3" + "192.168.1.4" + "192.168.1.5" + } + + -- Add 50 numbered settings to make the config large + settings {` + + // Add many numbered settings + var builder strings.Builder + builder.WriteString(largeConfig) + + for i := 1; i <= 50; i++ { + builder.WriteString("\n\t\tsetting") + builder.WriteString(strconv.Itoa(i)) + builder.WriteString(" ") + builder.WriteString(strconv.Itoa(i * 10)) + } + + // Close the settings block and add one more block + builder.WriteString(` + } + + roles { + admin { + permissions { + "read" + "write" + "delete" + "admin" + } + } + user { + permissions { + "read" + "write" + } + } + } + `) + + largeConfig = builder.String() + + b.ResetTimer() + for i := 0; i < b.N; i++ { + reader := strings.NewReader(largeConfig) + _, err := config.Load(reader) + if err != nil { + b.Fatalf("Failed to parse large config: %v", err) + } + } +} + +// JSON Benchmarks +func BenchmarkSmallConfigJSON(b *testing.B) { + smallConfigJSON := `{ + "host": "localhost", + "port": 8080, + "debug": true, + "timeout": 30 + }` + + b.ResetTimer() + for i := 0; i < b.N; i++ { + reader := strings.NewReader(smallConfigJSON) + var result map[string]interface{} + decoder := json.NewDecoder(reader) + err := decoder.Decode(&result) + if err != nil { + b.Fatalf("Failed to parse small JSON config: %v", err) + } + } +} + +func BenchmarkMediumConfigJSON(b *testing.B) { + mediumConfigJSON := `{ + "app": { + "name": "TestApp", + "version": "1.0.0", + "enableLogging": true + }, + "database": { + "host": "db.example.com", + "port": 5432, + "credentials": { + "username": "admin", + "password": "secure123" + } + }, + "features": [ + "authentication", + "authorization", + "reporting", + "analytics" + ], + "timeouts": { + "connect": 5, + "read": 10, + "write": 10, + "idle": 60 + }, + "endpoints": { + "api": "/api/v1", + "web": "/web", + "admin": "/admin", + "health": "/health" + } + }` + + b.ResetTimer() + for i := 0; i < b.N; i++ { + reader := strings.NewReader(mediumConfigJSON) + var result map[string]interface{} + decoder := json.NewDecoder(reader) + err := decoder.Decode(&result) + if err != nil { + b.Fatalf("Failed to parse medium JSON config: %v", err) + } + } +} + +func BenchmarkLargeConfigJSON(b *testing.B) { + // Start building the large JSON config + largeConfigJSON := `{ + "application": { + "name": "EnterpriseApp", + "version": "2.5.1", + "environment": "production", + "debug": false, + "maxConnections": 1000, + "timeout": 30, + "retryCount": 3, + "logLevel": "info" + }, + "databases": { + "primary": { + "host": "primary-db.example.com", + "port": 5432, + "maxConnections": 100, + "credentials": { + "username": "app_user", + "password": "super_secret", + "ssl": true, + "timeout": 5 + } + }, + "replica": { + "host": "replica-db.example.com", + "port": 5432, + "maxConnections": 200, + "credentials": { + "username": "read_user", + "password": "read_only_pw", + "ssl": true + } + } + }, + "allowedIPs": [ + "192.168.1.1", + "192.168.1.2", + "192.168.1.3", + "192.168.1.4", + "192.168.1.5" + ], + "settings": {` + + var builder strings.Builder + builder.WriteString(largeConfigJSON) + + // Add many numbered settings + for i := 1; i <= 50; i++ { + if i > 1 { + builder.WriteString(",") + } + builder.WriteString("\n\t\t\t\"setting") + builder.WriteString(strconv.Itoa(i)) + builder.WriteString("\": ") + builder.WriteString(strconv.Itoa(i * 10)) + } + + // Close the settings block and add roles + builder.WriteString(` + }, + "roles": { + "admin": { + "permissions": [ + "read", + "write", + "delete", + "admin" + ] + }, + "user": { + "permissions": [ + "read", + "write" + ] + } + } + }`) + + largeConfigJSONString := builder.String() + + b.ResetTimer() + for i := 0; i < b.N; i++ { + reader := strings.NewReader(largeConfigJSONString) + var result map[string]interface{} + decoder := json.NewDecoder(reader) + err := decoder.Decode(&result) + if err != nil { + b.Fatalf("Failed to parse large JSON config: %v", err) + } + } +} + +// YAML Benchmarks +func BenchmarkSmallConfigYAML(b *testing.B) { + smallConfigYAML := ` +host: localhost +port: 8080 +debug: true +timeout: 30 +` + + b.ResetTimer() + for i := 0; i < b.N; i++ { + var result map[string]interface{} + err := yaml.Unmarshal([]byte(smallConfigYAML), &result) + if err != nil { + b.Fatalf("Failed to parse small YAML config: %v", err) + } + } +} + +func BenchmarkMediumConfigYAML(b *testing.B) { + mediumConfigYAML := ` +app: + name: TestApp + version: 1.0.0 + enableLogging: true +database: + host: db.example.com + port: 5432 + credentials: + username: admin + password: secure123 +features: + - authentication + - authorization + - reporting + - analytics +timeouts: + connect: 5 + read: 10 + write: 10 + idle: 60 +# Comments to add some parsing overhead +endpoints: + api: /api/v1 + web: /web + admin: /admin + health: /health +` + + b.ResetTimer() + for i := 0; i < b.N; i++ { + var result map[string]interface{} + err := yaml.Unmarshal([]byte(mediumConfigYAML), &result) + if err != nil { + b.Fatalf("Failed to parse medium YAML config: %v", err) + } + } +} + +func BenchmarkLargeConfigYAML(b *testing.B) { + // Start building the large YAML config + largeConfigYAML := ` +application: + name: EnterpriseApp + version: 2.5.1 + environment: production + debug: false + maxConnections: 1000 + timeout: 30 + retryCount: 3 + logLevel: info + +# Database cluster configuration +databases: + primary: + host: primary-db.example.com + port: 5432 + maxConnections: 100 + credentials: + username: app_user + password: super_secret + ssl: true + timeout: 5 + replica: + host: replica-db.example.com + port: 5432 + maxConnections: 200 + credentials: + username: read_user + password: read_only_pw + ssl: true + +allowedIPs: + - 192.168.1.1 + - 192.168.1.2 + - 192.168.1.3 + - 192.168.1.4 + - 192.168.1.5 + +# Add 50 numbered settings to make the config large +settings: +` + + var builder strings.Builder + builder.WriteString(largeConfigYAML) + + // Add many numbered settings + for i := 1; i <= 50; i++ { + builder.WriteString(" setting") + builder.WriteString(strconv.Itoa(i)) + builder.WriteString(": ") + builder.WriteString(strconv.Itoa(i * 10)) + builder.WriteString("\n") + } + + // Add roles + builder.WriteString(` +roles: + admin: + permissions: + - read + - write + - delete + - admin + user: + permissions: + - read + - write +`) + + largeConfigYAMLString := builder.String() + + b.ResetTimer() + for i := 0; i < b.N; i++ { + var result map[string]interface{} + err := yaml.Unmarshal([]byte(largeConfigYAMLString), &result) + if err != nil { + b.Fatalf("Failed to parse large YAML config: %v", err) + } + } +} + +// TOML Benchmarks +func BenchmarkSmallConfigTOML(b *testing.B) { + smallConfigTOML := ` +host = "localhost" +port = 8080 +debug = true +timeout = 30 +` + + b.ResetTimer() + for i := 0; i < b.N; i++ { + var result map[string]interface{} + err := toml.Unmarshal([]byte(smallConfigTOML), &result) + if err != nil { + b.Fatalf("Failed to parse small TOML config: %v", err) + } + } +} + +func BenchmarkMediumConfigTOML(b *testing.B) { + mediumConfigTOML := ` +[app] +name = "TestApp" +version = "1.0.0" +enableLogging = true + +[database] +host = "db.example.com" +port = 5432 + +[database.credentials] +username = "admin" +password = "secure123" + +features = ["authentication", "authorization", "reporting", "analytics"] + +[timeouts] +connect = 5 +read = 10 +write = 10 +idle = 60 + +# Comments to add some parsing overhead +[endpoints] +api = "/api/v1" +web = "/web" +admin = "/admin" +health = "/health" +` + + b.ResetTimer() + for i := 0; i < b.N; i++ { + var result map[string]interface{} + err := toml.Unmarshal([]byte(mediumConfigTOML), &result) + if err != nil { + b.Fatalf("Failed to parse medium TOML config: %v", err) + } + } +} + +func BenchmarkLargeConfigTOML(b *testing.B) { + // Start building the large TOML config + largeConfigTOML := ` +[application] +name = "EnterpriseApp" +version = "2.5.1" +environment = "production" +debug = false +maxConnections = 1000 +timeout = 30 +retryCount = 3 +logLevel = "info" + +# Database cluster configuration +[databases.primary] +host = "primary-db.example.com" +port = 5432 +maxConnections = 100 + +[databases.primary.credentials] +username = "app_user" +password = "super_secret" +ssl = true +timeout = 5 + +[databases.replica] +host = "replica-db.example.com" +port = 5432 +maxConnections = 200 + +[databases.replica.credentials] +username = "read_user" +password = "read_only_pw" +ssl = true + +allowedIPs = ["192.168.1.1", "192.168.1.2", "192.168.1.3", "192.168.1.4", "192.168.1.5"] + +# Add 50 numbered settings to make the config large +[settings] +` + + var builder strings.Builder + builder.WriteString(largeConfigTOML) + + // Add many numbered settings + for i := 1; i <= 50; i++ { + builder.WriteString("setting") + builder.WriteString(strconv.Itoa(i)) + builder.WriteString(" = ") + builder.WriteString(strconv.Itoa(i * 10)) + builder.WriteString("\n") + } + + // Add roles + builder.WriteString(` +[roles.admin] +permissions = ["read", "write", "delete", "admin"] + +[roles.user] +permissions = ["read", "write"] +`) + + largeConfigTOMLString := builder.String() + + b.ResetTimer() + for i := 0; i < b.N; i++ { + var result map[string]interface{} + err := toml.Unmarshal([]byte(largeConfigTOMLString), &result) + if err != nil { + b.Fatalf("Failed to parse large TOML config: %v", err) + } + } +} diff --git a/pool.go b/pool.go index 10bcfe8..bcd55cc 100644 --- a/pool.go +++ b/pool.go @@ -6,8 +6,8 @@ import ( // byteSlicePool helps reuse byte slices var byteSlicePool = sync.Pool{ - New: func() interface{} { - b := make([]byte, 0, 128) + New: func() any { + b := make([]byte, 0, 64) return &b }, } @@ -27,8 +27,8 @@ func PutByteSlice(b *[]byte) { // mapPool helps reuse maps for config objects var mapPool = sync.Pool{ - New: func() interface{} { - m := make(map[string]any, 16) + New: func() any { + m := make(map[string]any, 8) return &m }, } @@ -51,8 +51,8 @@ func PutMap(m *map[string]any) { // arrayPool helps reuse slices var arrayPool = sync.Pool{ - New: func() interface{} { - a := make([]any, 0, 8) + New: func() any { + a := make([]any, 0, 4) return &a }, } diff --git a/scanner.go b/scanner.go index 68617b7..8ac6589 100644 --- a/scanner.go +++ b/scanner.go @@ -29,7 +29,7 @@ type Scanner struct { // scannerPool helps reuse scanner objects var scannerPool = sync.Pool{ - New: func() interface{} { + New: func() any { bufferRef := GetByteSlice() return &Scanner{ line: 1, @@ -43,7 +43,7 @@ var scannerPool = sync.Pool{ // NewScanner creates a new scanner from a pool func NewScanner(r io.Reader) *Scanner { s := scannerPool.Get().(*Scanner) - s.reader = bufio.NewReader(r) + s.reader = bufio.NewReaderSize(r, 1024) s.line = 1 s.col = 0 s.buffer = (*s.bufferRef)[:0]