Files
gibidify/cmd/benchmark/main.go
Ismo Vuorinen 3f65b813bd feat: update go to 1.25, add permissions and envs (#49)
* chore(ci): update go to 1.25, add permissions and envs
* fix(ci): update pr-lint.yml
* chore: update go, fix linting
* fix: tests and linting
* fix(lint): lint fixes, renovate should now pass
* fix: updates, security upgrades
* chore: workflow updates, lint
* fix: more lint, checkmake, and other fixes
* fix: more lint, convert scripts to POSIX compliant
* fix: simplify codeql workflow
* tests: increase test coverage, fix found issues
* fix(lint): editorconfig checking, add to linters
* fix(lint): shellcheck, add to linters
* fix(lint): apply cr comment suggestions
* fix(ci): remove step-security/harden-runner
* fix(lint): remove duplication, apply cr fixes
* fix(ci): tests in CI/CD pipeline
* chore(lint): deduplication of strings
* fix(lint): apply cr comment suggestions
* fix(ci): actionlint
* fix(lint): apply cr comment suggestions
* chore: lint, add deps management
2025-10-10 12:14:42 +03:00

186 lines
4.8 KiB
Go

// Package main provides a CLI for running gibidify benchmarks.
package main
import (
"flag"
"fmt"
"os"
"runtime"
"strings"
"github.com/ivuorinen/gibidify/benchmark"
"github.com/ivuorinen/gibidify/gibidiutils"
)
var (
sourceDir = flag.String("source", "", "Source directory to benchmark (uses temp files if empty)")
benchmarkType = flag.String("type", "all", "Benchmark type: all, collection, processing, concurrency, format")
format = flag.String("format", "json", "Output format for processing benchmarks")
concurrency = flag.Int("concurrency", runtime.NumCPU(), "Concurrency level for processing benchmarks")
concurrencyList = flag.String("concurrency-list", "1,2,4,8", "Comma-separated list of concurrency levels")
formatList = flag.String("format-list", "json,yaml,markdown", "Comma-separated list of formats")
numFiles = flag.Int("files", 100, "Number of files to create for benchmarks")
)
func main() {
flag.Parse()
if err := runBenchmarks(); err != nil {
_, _ = fmt.Fprintf(os.Stderr, "Benchmark failed: %v\n", err)
os.Exit(1)
}
}
func runBenchmarks() error {
fmt.Printf("Running gibidify benchmarks...\n")
fmt.Printf("Source: %s\n", getSourceDescription())
fmt.Printf("Type: %s\n", *benchmarkType)
fmt.Printf("CPU cores: %d\n", runtime.NumCPU())
fmt.Println()
switch *benchmarkType {
case "all":
return benchmark.RunAllBenchmarks(*sourceDir)
case "collection":
return runCollectionBenchmark()
case "processing":
return runProcessingBenchmark()
case "concurrency":
return runConcurrencyBenchmark()
case "format":
return runFormatBenchmark()
default:
return gibidiutils.NewValidationError(
gibidiutils.CodeValidationFormat,
"invalid benchmark type: "+*benchmarkType,
)
}
}
func runCollectionBenchmark() error {
fmt.Println("Running file collection benchmark...")
result, err := benchmark.FileCollectionBenchmark(*sourceDir, *numFiles)
if err != nil {
return gibidiutils.WrapError(
err,
gibidiutils.ErrorTypeProcessing,
gibidiutils.CodeProcessingCollection,
"file collection benchmark failed",
)
}
benchmark.PrintResult(result)
return nil
}
func runProcessingBenchmark() error {
fmt.Printf("Running file processing benchmark (format: %s, concurrency: %d)...\n", *format, *concurrency)
result, err := benchmark.FileProcessingBenchmark(*sourceDir, *format, *concurrency)
if err != nil {
return gibidiutils.WrapError(
err,
gibidiutils.ErrorTypeProcessing,
gibidiutils.CodeProcessingCollection,
"file processing benchmark failed",
)
}
benchmark.PrintResult(result)
return nil
}
func runConcurrencyBenchmark() error {
concurrencyLevels, err := parseConcurrencyList(*concurrencyList)
if err != nil {
return gibidiutils.WrapError(
err,
gibidiutils.ErrorTypeValidation,
gibidiutils.CodeValidationFormat,
"invalid concurrency list",
)
}
fmt.Printf("Running concurrency benchmark (format: %s, levels: %v)...\n", *format, concurrencyLevels)
suite, err := benchmark.ConcurrencyBenchmark(*sourceDir, *format, concurrencyLevels)
if err != nil {
return gibidiutils.WrapError(
err,
gibidiutils.ErrorTypeProcessing,
gibidiutils.CodeProcessingCollection,
"concurrency benchmark failed",
)
}
benchmark.PrintSuite(suite)
return nil
}
func runFormatBenchmark() error {
formats := parseFormatList(*formatList)
fmt.Printf("Running format benchmark (formats: %v)...\n", formats)
suite, err := benchmark.FormatBenchmark(*sourceDir, formats)
if err != nil {
return gibidiutils.WrapError(
err,
gibidiutils.ErrorTypeProcessing,
gibidiutils.CodeProcessingCollection,
"format benchmark failed",
)
}
benchmark.PrintSuite(suite)
return nil
}
func getSourceDescription() string {
if *sourceDir == "" {
return fmt.Sprintf("temporary files (%d files)", *numFiles)
}
return *sourceDir
}
func parseConcurrencyList(list string) ([]int, error) {
parts := strings.Split(list, ",")
levels := make([]int, 0, len(parts))
for _, part := range parts {
part = strings.TrimSpace(part)
var level int
if _, err := fmt.Sscanf(part, "%d", &level); err != nil {
return nil, gibidiutils.WrapErrorf(
err,
gibidiutils.ErrorTypeValidation,
gibidiutils.CodeValidationFormat,
"invalid concurrency level: %s",
part,
)
}
if level <= 0 {
return nil, gibidiutils.NewValidationError(
gibidiutils.CodeValidationFormat,
"concurrency level must be positive: "+part,
)
}
levels = append(levels, level)
}
if len(levels) == 0 {
return nil, gibidiutils.NewValidationError(
gibidiutils.CodeValidationFormat,
"no valid concurrency levels found",
)
}
return levels, nil
}
func parseFormatList(list string) []string {
parts := strings.Split(list, ",")
formats := make([]string, 0, len(parts))
for _, part := range parts {
part = strings.TrimSpace(part)
if part != "" {
formats = append(formats, part)
}
}
return formats
}