1
0

conservative_worker_benchmark_test.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. package nginx_log
  2. import (
  3. "context"
  4. "fmt"
  5. "os"
  6. "path/filepath"
  7. "runtime"
  8. "testing"
  9. "time"
  10. "github.com/0xJacky/Nginx-UI/internal/nginx_log/indexer"
  11. "github.com/0xJacky/Nginx-UI/internal/nginx_log/parser"
  12. )
  13. // BenchmarkConservativeWorkerScaling tests lower worker multipliers to show clearer performance differences
  14. func BenchmarkConservativeWorkerScaling(b *testing.B) {
  15. recordCount := 10000 // Moderate dataset for clear differences
  16. // Test lower multipliers to show more obvious improvements
  17. testConfigs := []struct {
  18. name string
  19. multiplier float64
  20. }{
  21. {"0.5x_CPU_Conservative", 0.5},
  22. {"1x_CPU_Old_Default", 1.0},
  23. {"1.5x_CPU_Moderate", 1.5},
  24. {"2x_CPU_Previous_Default", 2.0},
  25. {"3x_CPU_New_Default", 3.0},
  26. {"4x_CPU_High_Throughput", 4.0},
  27. }
  28. // Generate test data once
  29. tempDir := b.TempDir()
  30. testLogFile := filepath.Join(tempDir, "access.log")
  31. if err := generateConservativeTestData(testLogFile, recordCount); err != nil {
  32. b.Fatalf("Failed to generate test data: %v", err)
  33. }
  34. for _, tc := range testConfigs {
  35. b.Run(tc.name, func(b *testing.B) {
  36. cpuCount := runtime.GOMAXPROCS(0)
  37. workerCount := int(float64(cpuCount) * tc.multiplier)
  38. if workerCount < 1 {
  39. workerCount = 1
  40. }
  41. b.ResetTimer()
  42. for i := 0; i < b.N; i++ {
  43. indexDir := filepath.Join(tempDir, fmt.Sprintf("index_%s_%d", tc.name, i))
  44. // Create config with specific worker count
  45. config := indexer.DefaultIndexerConfig()
  46. config.IndexPath = indexDir
  47. config.WorkerCount = workerCount
  48. config.EnableMetrics = false
  49. // Run test
  50. start := time.Now()
  51. result := runConservativeWorkerTest(b, config, testLogFile)
  52. duration := time.Since(start)
  53. // Report metrics
  54. throughput := float64(result.Processed) / duration.Seconds()
  55. b.ReportMetric(throughput, "records/sec")
  56. b.ReportMetric(float64(workerCount), "workers")
  57. b.ReportMetric(float64(result.Processed), "processed")
  58. if i == 0 {
  59. b.Logf("Multiplier=%.1fx, Workers=%d, Processed=%d, Duration=%v, Throughput=%.0f rec/s",
  60. tc.multiplier, workerCount, result.Processed, duration, throughput)
  61. }
  62. }
  63. })
  64. }
  65. }
  66. type ConservativeTestResult struct {
  67. Processed int
  68. Duration time.Duration
  69. }
  70. func runConservativeWorkerTest(b *testing.B, config *indexer.Config, logFile string) *ConservativeTestResult {
  71. ctx := context.Background()
  72. // Parser setup with proportional worker count
  73. parserConfig := &parser.Config{
  74. MaxLineLength: 4 * 1024,
  75. WorkerCount: max(1, config.WorkerCount / 3), // Parser uses 1/3 of indexer workers
  76. BatchSize: 500,
  77. }
  78. optimizedParser := parser.NewOptimizedParser(
  79. parserConfig,
  80. nil, // No UA parser for speed
  81. nil, // No Geo service for speed
  82. )
  83. // Parse only for consistent measurement
  84. file, err := os.Open(logFile)
  85. if err != nil {
  86. b.Fatalf("Failed to open log file: %v", err)
  87. }
  88. defer file.Close()
  89. parseResult, err := optimizedParser.OptimizedParseStream(ctx, file)
  90. if err != nil {
  91. b.Fatalf("Parsing failed: %v", err)
  92. }
  93. return &ConservativeTestResult{
  94. Processed: parseResult.Processed,
  95. Duration: parseResult.Duration,
  96. }
  97. }
  98. func generateConservativeTestData(filename string, recordCount int) error {
  99. file, err := os.Create(filename)
  100. if err != nil {
  101. return err
  102. }
  103. defer file.Close()
  104. baseTime := time.Now().Unix()
  105. for i := 0; i < recordCount; i++ {
  106. logLine := fmt.Sprintf(
  107. `192.168.1.%d - - [%s] "GET /api/test%d HTTP/1.1" 200 %d "-" "Test/1.0" 0.001`,
  108. i%256,
  109. time.Unix(baseTime+int64(i), 0).Format("02/Jan/2006:15:04:05 -0700"),
  110. i%100,
  111. 1000+i%1000,
  112. )
  113. fmt.Fprintln(file, logLine)
  114. }
  115. return nil
  116. }
  117. func max(a, b int) int {
  118. if a > b {
  119. return a
  120. }
  121. return b
  122. }