@@ -7,18 +7,13 @@ import (
77 "bytes"
88 "context"
99 "fmt"
10- "log"
11- "runtime"
1210 "runtime/metrics"
13- "sort"
1411 "strconv"
15- "sync"
1612 "time"
1713
1814 "github.com/aws/aws-sdk-go-v2/aws"
1915 "github.com/aws/aws-sdk-go-v2/service/dynamodb"
2016 "github.com/aws/aws-sdk-go-v2/service/dynamodb/types"
21- "github.com/schollz/progressbar/v3"
2217)
2318
2419// === Helper Functions ===
@@ -139,76 +134,6 @@ func (b *DBESDKBenchmark) shouldRunTestType(testType string) bool {
139134 return false
140135}
141136
142- // === Throughput Test Implementation ===
143-
144- // runThroughputTest runs throughput benchmark test
145- func (b * DBESDKBenchmark ) runThroughputTest (dataSize int , iterations int ) (* BenchmarkResult , error ) {
146- log .Printf ("Running throughput test - Size: %d bytes, Iterations: %d" , dataSize , iterations )
147-
148- testData := b .GenerateTestData (dataSize )
149-
150- // Warmup
151- for i := 0 ; i < b .Config .Iterations .Warmup ; i ++ {
152- if _ , _ , err := b .runBatchPutGetCycle (testData ); err != nil {
153- return nil , fmt .Errorf ("warmup iteration %d failed: %w" , i , err )
154- }
155- }
156-
157- // Measurement runs
158- var putLatencies , getLatencies , endToEndLatencies []float64
159- var totalBytes int64
160-
161- bar := progressbar .NewOptions (iterations ,
162- progressbar .OptionSetDescription ("Throughput test" ),
163- progressbar .OptionShowCount (),
164- progressbar .OptionSetWidth (50 ),
165- )
166-
167- startTime := time .Now ()
168- for i := 0 ; i < iterations ; i ++ {
169- iterationStart := time .Now ()
170- putMs , getMs , err := b .runBatchPutGetCycle (testData )
171- if err != nil {
172- return nil , fmt .Errorf ("measurement iteration %d failed: %w" , i , err )
173- }
174- iterationDuration := time .Since (iterationStart ).Seconds () * 1000
175-
176- putLatencies = append (putLatencies , putMs )
177- getLatencies = append (getLatencies , getMs )
178- endToEndLatencies = append (endToEndLatencies , iterationDuration )
179- totalBytes += int64 (dataSize )
180-
181- bar .Add (1 )
182- }
183- totalDuration := time .Since (startTime ).Seconds ()
184-
185- // Calculate metrics
186- sort .Float64s (endToEndLatencies )
187- result := & BenchmarkResult {
188- TestName : "throughput" ,
189- Language : "go" ,
190- DataSize : dataSize ,
191- Concurrency : 1 ,
192- PutLatencyMs : Average (putLatencies ),
193- GetLatencyMs : Average (getLatencies ),
194- EndToEndLatencyMs : Average (endToEndLatencies ),
195- OpsPerSecond : float64 (iterations ) / totalDuration ,
196- BytesPerSecond : float64 (totalBytes ) / totalDuration ,
197- P50Latency : Percentile (endToEndLatencies , 0.50 ),
198- P95Latency : Percentile (endToEndLatencies , 0.95 ),
199- P99Latency : Percentile (endToEndLatencies , 0.99 ),
200- Timestamp : time .Now ().Format ("2006-01-02 15:04:05" ),
201- GoVersion : runtime .Version (),
202- CPUCount : b .CPUCount ,
203- TotalMemoryGB : b .TotalMemoryGB ,
204- }
205-
206- log .Printf ("Throughput test completed - Ops/sec: %.2f, MB/sec: %.2f" ,
207- result .OpsPerSecond , result .BytesPerSecond / (1024 * 1024 ))
208-
209- return result , nil
210- }
211-
212137// === Memory Test Implementation ===
213138
214139// sampleMemoryContinuously runs continuous memory sampling during operation
@@ -245,270 +170,3 @@ func (b *DBESDKBenchmark) sampleMemoryContinuously(beforeHeap, beforeAllocs uint
245170 }
246171 }
247172}
248-
249- // runMemoryTest runs memory benchmark with continuous sampling
250- func (b * DBESDKBenchmark ) runMemoryTest (dataSize int ) (* BenchmarkResult , error ) {
251- log .Printf ("Running memory test - Size: %d bytes (%d iterations, continuous sampling)" , dataSize , MemoryTestIterations )
252-
253- data := b .GenerateTestData (dataSize )
254-
255- // Setup runtime/metrics tracking
256- samples := make ([]metrics.Sample , 2 )
257- samples [0 ].Name = "/memory/classes/heap/objects:bytes"
258- samples [1 ].Name = "/gc/heap/allocs:bytes"
259-
260- var peakHeap , peakAllocations float64
261- var avgHeapValues []float64
262-
263- // Run iterations
264- for i := 0 ; i < MemoryTestIterations ; i ++ {
265- runtime .GC ()
266- time .Sleep (GCSettleTimeMs * time .Millisecond )
267-
268- // Get baseline
269- metrics .Read (samples )
270- beforeHeap := samples [0 ].Value .Uint64 ()
271- beforeAllocs := samples [1 ].Value .Uint64 ()
272-
273- // Start continuous sampling
274- stopSampling := make (chan bool )
275- var continuousSamples []MemorySample
276- var samplingMutex sync.Mutex
277-
278- go func () {
279- sampledData := b .sampleMemoryContinuously (beforeHeap , beforeAllocs , stopSampling )
280- samplingMutex .Lock ()
281- continuousSamples = sampledData
282- samplingMutex .Unlock ()
283- }()
284-
285- // Run operation
286- operationStart := time .Now ()
287- _ , _ , err := b .runBatchPutGetCycle (data )
288- operationDuration := time .Since (operationStart )
289-
290- close (stopSampling )
291- time .Sleep (FinalSampleWaitMs * time .Millisecond )
292-
293- if err != nil {
294- log .Printf ("Iteration %d failed: %v" , i + 1 , err )
295- continue
296- }
297-
298- // Analyze samples
299- samplingMutex .Lock ()
300- var iterPeakHeap , iterTotalAllocs , iterAvgHeap float64
301- if len (continuousSamples ) > 0 {
302- var heapSum float64
303- for _ , s := range continuousSamples {
304- if s .HeapMB > iterPeakHeap {
305- iterPeakHeap = s .HeapMB
306- }
307- if s .MetricsAllocsMB > iterTotalAllocs {
308- iterTotalAllocs = s .MetricsAllocsMB
309- }
310- heapSum += s .HeapMB
311- }
312- iterAvgHeap = heapSum / float64 (len (continuousSamples ))
313- }
314- samplingMutex .Unlock ()
315-
316- // Update global metrics
317- if iterPeakHeap > peakHeap {
318- peakHeap = iterPeakHeap
319- }
320- if iterTotalAllocs > peakAllocations {
321- peakAllocations = iterTotalAllocs
322- }
323- avgHeapValues = append (avgHeapValues , iterAvgHeap )
324-
325- log .Printf ("=== Iteration %d === Peak Heap: %.2f MB, Total Allocs: %.2f MB, Avg Heap: %.2f MB (%v, %d samples)" ,
326- i + 1 , iterPeakHeap , iterTotalAllocs , iterAvgHeap , operationDuration , len (continuousSamples ))
327- }
328-
329- if len (avgHeapValues ) == 0 {
330- return nil , fmt .Errorf ("all memory test iterations failed" )
331- }
332-
333- overallAvgHeap := Average (avgHeapValues )
334- memoryEfficiency := float64 (dataSize ) / (overallAvgHeap * 1024 * 1024 )
335- if overallAvgHeap == 0 {
336- memoryEfficiency = 0
337- }
338-
339- log .Printf ("\n Memory Summary:" )
340- log .Printf ("- Absolute Peak Heap: %.2f MB (across all runs)" , peakHeap )
341- log .Printf ("- Average Heap: %.2f MB (across all runs)" , overallAvgHeap )
342- log .Printf ("- Total Allocations: %.2f MB (max across all runs)" , peakAllocations )
343-
344- result := & BenchmarkResult {
345- TestName : "memory" ,
346- Language : "go" ,
347- DataSize : dataSize ,
348- Concurrency : 1 ,
349- PeakMemoryMB : peakHeap ,
350- MemoryEfficiency : memoryEfficiency ,
351- Timestamp : time .Now ().Format ("2006-01-02 15:04:05" ),
352- GoVersion : runtime .Version (),
353- CPUCount : b .CPUCount ,
354- TotalMemoryGB : b .TotalMemoryGB ,
355- }
356-
357- return result , nil
358- }
359-
360- // === Concurrent Test Implementation ===
361-
362- // runConcurrentTest runs concurrent operations benchmark test
363- func (b * DBESDKBenchmark ) runConcurrentTest (dataSize int , concurrency int , iterationsPerWorker int ) (* BenchmarkResult , error ) {
364- log .Printf ("Running concurrent test - Size: %d bytes, Concurrency: %d" , dataSize , concurrency )
365-
366- data := b .GenerateTestData (dataSize )
367- var allTimes []float64
368- var timesMutex sync.Mutex
369- var wg sync.WaitGroup
370-
371- errorChan := make (chan error , concurrency )
372- startTime := time .Now ()
373-
374- // Launch workers
375- for i := 0 ; i < concurrency ; i ++ {
376- wg .Add (1 )
377- go func (workerID int ) {
378- defer wg .Done ()
379-
380- var workerTimes []float64
381- for j := 0 ; j < iterationsPerWorker ; j ++ {
382- iterStart := time .Now ()
383- _ , _ , err := b .runBatchPutGetCycle (data )
384- if err != nil {
385- errorChan <- fmt .Errorf ("worker %d iteration %d failed: %w" , workerID , j , err )
386- return
387- }
388- workerTimes = append (workerTimes , time .Since (iterStart ).Seconds ()* 1000 )
389- }
390-
391- timesMutex .Lock ()
392- allTimes = append (allTimes , workerTimes ... )
393- timesMutex .Unlock ()
394- }(i )
395- }
396-
397- wg .Wait ()
398- totalDuration := time .Since (startTime ).Seconds ()
399-
400- // Check for errors
401- select {
402- case err := <- errorChan :
403- return nil , err
404- default :
405- }
406-
407- // Calculate metrics
408- totalOps := concurrency * iterationsPerWorker
409- totalBytes := int64 (totalOps * dataSize )
410-
411- sort .Float64s (allTimes )
412- result := & BenchmarkResult {
413- TestName : "concurrent" ,
414- Language : "go" ,
415- DataSize : dataSize ,
416- Concurrency : concurrency ,
417- EndToEndLatencyMs : Average (allTimes ),
418- OpsPerSecond : float64 (totalOps ) / totalDuration ,
419- BytesPerSecond : float64 (totalBytes ) / totalDuration ,
420- P50Latency : Percentile (allTimes , 0.50 ),
421- P95Latency : Percentile (allTimes , 0.95 ),
422- P99Latency : Percentile (allTimes , 0.99 ),
423- Timestamp : time .Now ().Format ("2006-01-02 15:04:05" ),
424- GoVersion : runtime .Version (),
425- CPUCount : b .CPUCount ,
426- TotalMemoryGB : b .TotalMemoryGB ,
427- }
428-
429- log .Printf ("Concurrent test completed - Ops/sec: %.2f, Avg latency: %.2f ms" ,
430- result .OpsPerSecond , result .EndToEndLatencyMs )
431-
432- return result , nil
433- }
434-
435- // === Test Orchestration ===
436-
437- // runThroughputTests executes all throughput tests
438- func (b * DBESDKBenchmark ) runThroughputTests (dataSizes []int , iterations int ) {
439- log .Println ("Running throughput tests..." )
440- for _ , dataSize := range dataSizes {
441- result , err := b .runThroughputTest (dataSize , iterations )
442- if err != nil {
443- log .Printf ("Throughput test failed: %v" , err )
444- continue
445- }
446- b .Results = append (b .Results , * result )
447- log .Printf ("Throughput test completed: %.2f ops/sec" , result .OpsPerSecond )
448- }
449- }
450-
451- // runMemoryTests executes all memory tests
452- func (b * DBESDKBenchmark ) runMemoryTests (dataSizes []int ) {
453- log .Println ("Running memory tests..." )
454- for _ , dataSize := range dataSizes {
455- result , err := b .runMemoryTest (dataSize )
456- if err != nil {
457- log .Printf ("Memory test failed: %v" , err )
458- continue
459- }
460- b .Results = append (b .Results , * result )
461- log .Printf ("Memory test completed: %.2f MB peak" , result .PeakMemoryMB )
462- }
463- }
464-
465- // runConcurrencyTests executes all concurrency tests
466- func (b * DBESDKBenchmark ) runConcurrencyTests (dataSizes []int , concurrencyLevels []int ) {
467- log .Println ("Running concurrency tests..." )
468- for _ , dataSize := range dataSizes {
469- for _ , concurrency := range concurrencyLevels {
470- if concurrency > 1 { // Skip single-threaded
471- result , err := b .runConcurrentTest (dataSize , concurrency , 5 )
472- if err != nil {
473- log .Printf ("Concurrent test failed: %v" , err )
474- continue
475- }
476- b .Results = append (b .Results , * result )
477- log .Printf ("Concurrent test completed: %.2f ops/sec @ %d threads" , result .OpsPerSecond , concurrency )
478- }
479- }
480- }
481- }
482-
483- // RunAllBenchmarks runs all configured benchmark tests
484- func (b * DBESDKBenchmark ) RunAllBenchmarks () error {
485- log .Println ("Starting comprehensive DB-ESDK benchmark suite" )
486-
487- // Combine all data sizes
488- var dataSizes []int
489- for _ , sizes := range [][]int {b .Config .DataSizes .Small , b .Config .DataSizes .Medium , b .Config .DataSizes .Large } {
490- dataSizes = append (dataSizes , sizes ... )
491- }
492-
493- // Run test suites
494- if b .shouldRunTestType ("throughput" ) {
495- b .runThroughputTests (dataSizes , b .Config .Iterations .Measurement )
496- } else {
497- log .Println ("Skipping throughput tests (not in test_types)" )
498- }
499-
500- if b .shouldRunTestType ("memory" ) {
501- b .runMemoryTests (dataSizes )
502- } else {
503- log .Println ("Skipping memory tests (not in test_types)" )
504- }
505-
506- if b .shouldRunTestType ("concurrency" ) {
507- b .runConcurrencyTests (dataSizes , b .Config .ConcurrencyLevels )
508- } else {
509- log .Println ("Skipping concurrency tests (not in test_types)" )
510- }
511-
512- log .Printf ("Benchmark suite completed. Total results: %d" , len (b .Results ))
513- return nil
514- }
0 commit comments