progress_tracker_bench_test.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. package indexer
  2. import (
  3. "context"
  4. "fmt"
  5. "sync"
  6. "testing"
  7. "time"
  8. )
  9. func BenchmarkProgressTracker_UpdateFileProgress(b *testing.B) {
  10. tracker := NewProgressTracker("/var/log/nginx/benchmark.log", nil)
  11. // Add a file
  12. tracker.AddFile("/var/log/nginx/access.log", false)
  13. tracker.SetFileEstimate("/var/log/nginx/access.log", 100000)
  14. tracker.StartFile("/var/log/nginx/access.log")
  15. b.ResetTimer()
  16. b.ReportAllocs()
  17. for i := 0; i < b.N; i++ {
  18. tracker.UpdateFileProgress("/var/log/nginx/access.log", int64(i))
  19. }
  20. }
  21. func BenchmarkProgressTracker_GetProgress(b *testing.B) {
  22. tracker := NewProgressTracker("/var/log/nginx/benchmark.log", nil)
  23. // Add multiple files to make it realistic
  24. for i := 0; i < 10; i++ {
  25. fileName := fmt.Sprintf("/var/log/nginx/access-%d.log", i)
  26. tracker.AddFile(fileName, false)
  27. tracker.SetFileEstimate(fileName, 10000)
  28. tracker.StartFile(fileName)
  29. tracker.UpdateFileProgress(fileName, int64(i*1000))
  30. }
  31. b.ResetTimer()
  32. b.ReportAllocs()
  33. for i := 0; i < b.N; i++ {
  34. _ = tracker.GetProgress()
  35. }
  36. }
  37. func BenchmarkProgressTracker_GetAllFiles(b *testing.B) {
  38. tracker := NewProgressTracker("/var/log/nginx/benchmark.log", nil)
  39. // Add many files
  40. for i := 0; i < 100; i++ {
  41. fileName := fmt.Sprintf("/var/log/nginx/access-%d.log", i)
  42. tracker.AddFile(fileName, false)
  43. tracker.SetFileEstimate(fileName, 10000)
  44. }
  45. b.ResetTimer()
  46. b.ReportAllocs()
  47. for i := 0; i < b.N; i++ {
  48. _ = tracker.GetAllFiles()
  49. }
  50. }
  51. func BenchmarkProgressTracker_ConcurrentAccess(b *testing.B) {
  52. tracker := NewProgressTracker("/var/log/nginx/benchmark.log", nil)
  53. // Add files
  54. fileCount := 10
  55. for i := 0; i < fileCount; i++ {
  56. fileName := fmt.Sprintf("/var/log/nginx/access-%d.log", i)
  57. tracker.AddFile(fileName, false)
  58. tracker.SetFileEstimate(fileName, 10000)
  59. tracker.StartFile(fileName)
  60. }
  61. b.ResetTimer()
  62. b.ReportAllocs()
  63. b.RunParallel(func(pb *testing.PB) {
  64. i := 0
  65. for pb.Next() {
  66. // Mix of operations
  67. switch i % 4 {
  68. case 0:
  69. // Update progress
  70. fileName := fmt.Sprintf("/var/log/nginx/access-%d.log", i%fileCount)
  71. tracker.UpdateFileProgress(fileName, int64(i))
  72. case 1:
  73. // Get progress
  74. _ = tracker.GetProgress()
  75. case 2:
  76. // Get file progress
  77. fileName := fmt.Sprintf("/var/log/nginx/access-%d.log", i%fileCount)
  78. _, _ = tracker.GetFileProgress(fileName)
  79. case 3:
  80. // Get all files
  81. _ = tracker.GetAllFiles()
  82. }
  83. i++
  84. }
  85. })
  86. }
  87. func BenchmarkProgressManager_GetTracker(b *testing.B) {
  88. manager := NewProgressManager()
  89. config := &ProgressConfig{}
  90. b.ResetTimer()
  91. b.ReportAllocs()
  92. for i := 0; i < b.N; i++ {
  93. logPath := fmt.Sprintf("/var/log/nginx/access-%d.log", i%100) // Reuse some paths
  94. _ = manager.GetTracker(logPath, config)
  95. }
  96. }
  97. func BenchmarkProgressManager_ConcurrentAccess(b *testing.B) {
  98. manager := NewProgressManager()
  99. config := &ProgressConfig{}
  100. b.ResetTimer()
  101. b.ReportAllocs()
  102. b.RunParallel(func(pb *testing.PB) {
  103. i := 0
  104. for pb.Next() {
  105. switch i % 3 {
  106. case 0:
  107. // Get tracker
  108. logPath := fmt.Sprintf("/var/log/nginx/access-%d.log", i%50)
  109. _ = manager.GetTracker(logPath, config)
  110. case 1:
  111. // Get all trackers
  112. _ = manager.GetAllTrackers()
  113. case 2:
  114. // Remove tracker
  115. logPath := fmt.Sprintf("/var/log/nginx/access-%d.log", i%50)
  116. manager.RemoveTracker(logPath)
  117. }
  118. i++
  119. }
  120. })
  121. }
  122. func BenchmarkEstimateFileLines_NonExistent(b *testing.B) {
  123. ctx := context.Background()
  124. b.ResetTimer()
  125. b.ReportAllocs()
  126. for i := 0; i < b.N; i++ {
  127. _, _ = EstimateFileLines(ctx, "/nonexistent/file.log", 100000, false)
  128. }
  129. }
  130. func BenchmarkProgressTracker_CompleteWorkflow(b *testing.B) {
  131. // Benchmark a complete workflow: add files, process them, complete them
  132. b.ResetTimer()
  133. b.ReportAllocs()
  134. for i := 0; i < b.N; i++ {
  135. b.StopTimer()
  136. logPath := fmt.Sprintf("/var/log/nginx/benchmark-%d.log", i)
  137. tracker := NewProgressTracker(logPath, nil)
  138. b.StartTimer()
  139. // Add files
  140. for j := 0; j < 5; j++ {
  141. fileName := fmt.Sprintf("%s.%d", logPath, j)
  142. tracker.AddFile(fileName, j%2 == 0) // Mix compressed and uncompressed
  143. tracker.SetFileEstimate(fileName, 1000)
  144. tracker.SetFileSize(fileName, 150000)
  145. }
  146. // Process files
  147. for j := 0; j < 5; j++ {
  148. fileName := fmt.Sprintf("%s.%d", logPath, j)
  149. tracker.StartFile(fileName)
  150. // Simulate progress updates
  151. for k := 0; k < 10; k++ {
  152. tracker.UpdateFileProgress(fileName, int64(k*100))
  153. }
  154. tracker.CompleteFile(fileName, 1000)
  155. }
  156. // Get final progress
  157. _ = tracker.GetProgress()
  158. }
  159. }
  160. func BenchmarkProgressTracker_NotificationOverhead(b *testing.B) {
  161. var notificationCount int64
  162. var mu sync.Mutex
  163. config := &ProgressConfig{
  164. OnProgress: func(pn ProgressNotification) {
  165. mu.Lock()
  166. notificationCount++
  167. mu.Unlock()
  168. },
  169. OnCompletion: func(cn CompletionNotification) {
  170. mu.Lock()
  171. notificationCount++
  172. mu.Unlock()
  173. },
  174. }
  175. b.ResetTimer()
  176. b.ReportAllocs()
  177. for i := 0; i < b.N; i++ {
  178. b.StopTimer()
  179. tracker := NewProgressTracker(fmt.Sprintf("/var/log/nginx/bench-%d.log", i), config)
  180. tracker.AddFile(fmt.Sprintf("/var/log/nginx/bench-%d.log", i), false)
  181. tracker.SetFileEstimate(fmt.Sprintf("/var/log/nginx/bench-%d.log", i), 1000)
  182. b.StartTimer()
  183. tracker.StartFile(fmt.Sprintf("/var/log/nginx/bench-%d.log", i))
  184. // Multiple rapid updates to test throttling
  185. for j := 0; j < 100; j++ {
  186. tracker.UpdateFileProgress(fmt.Sprintf("/var/log/nginx/bench-%d.log", i), int64(j*10))
  187. }
  188. tracker.CompleteFile(fmt.Sprintf("/var/log/nginx/bench-%d.log", i), 1000)
  189. }
  190. // Brief wait for any pending notifications
  191. time.Sleep(time.Millisecond)
  192. }
  193. func BenchmarkProgressTracker_MemoryUsage(b *testing.B) {
  194. // Benchmark memory usage with many files
  195. tracker := NewProgressTracker("/var/log/nginx/memory-test.log", nil)
  196. b.ResetTimer()
  197. b.ReportAllocs()
  198. for i := 0; i < b.N; i++ {
  199. fileName := fmt.Sprintf("/var/log/nginx/access-%d.log", i)
  200. tracker.AddFile(fileName, false)
  201. tracker.SetFileEstimate(fileName, 10000)
  202. tracker.SetFileSize(fileName, 1500000)
  203. if i%100 == 0 {
  204. // Periodically check progress to ensure data structures are used
  205. _ = tracker.GetProgress()
  206. }
  207. }
  208. }