1- using System . Linq ;
1+ using Microsoft . Extensions . Logging ;
22
33namespace BenchmarkRunner . Utils ;
44
55public static class Helpers
66{
7+ private static readonly ILoggerFactory LoggerFactory = Microsoft . Extensions . Logging . LoggerFactory . Create ( builder =>
8+ {
9+ builder
10+ . AddConsole ( )
11+ . SetMinimumLevel ( LogLevel . Information ) ;
12+ } ) ;
13+
14+ public static ILogger < T > CreateLogger < T > ( ) => LoggerFactory . CreateLogger < T > ( ) ;
15+
716 public static void InvokeGarbageCollection ( )
817 {
918 GC . Collect ( ) ;
1019 GC . WaitForPendingFinalizers ( ) ;
1120 GC . Collect ( ) ;
1221 }
1322
14- public static async Task InsertInBatchesAsync < T > ( List < T > items , int batchSize , Func < List < T > , Task > insertBatch )
23+ /// <summary>
24+ /// Formats elapsed time in a human-readable format (e.g., "1m 23.45s" or "45.67s")
25+ /// </summary>
26+ public static string FormatElapsedTime ( TimeSpan elapsed )
1527 {
16- for ( int i = 0 ; i < items . Count ; i += batchSize )
28+ if ( elapsed . TotalMinutes >= 1 )
1729 {
18- var batch = items . Skip ( i ) . Take ( batchSize ) . ToList ( ) ;
19- await insertBatch ( batch ) ;
30+ var minutes = ( int ) elapsed . TotalMinutes ;
31+ var seconds = elapsed . TotalSeconds % 60 ;
32+ return $ "{ minutes } m { seconds : F2} s";
2033 }
34+ return $ "{ elapsed . TotalSeconds : F2} s";
35+ }
36+
37+ public static async Task InsertInBatchesAsync < T > ( List < T > items , int batchSize , Func < List < T > , Task > insertBatch )
38+ {
39+ var batches = items . Chunk ( batchSize ) ;
40+ foreach ( var batch in batches )
41+ await insertBatch ( [ .. batch ] ) ;
2142 }
2243
2344 private static int CalculateMaxConcurrency ( int totalTasks , int maxConcurrency )
@@ -32,20 +53,20 @@ public static async Task<List<T>> ExecuteConcurrentlyAsync<T>(
3253 Func < int , Task < List < T > > > taskFactory )
3354 {
3455 maxConcurrency = CalculateMaxConcurrency ( totalTasks , maxConcurrency ) ;
35- var semaphore = new SemaphoreSlim ( maxConcurrency , maxConcurrency ) ;
56+ using var semaphore = new SemaphoreSlim ( maxConcurrency , maxConcurrency ) ;
3657 var tasks = new List < Task < List < T > > > ( ) ;
3758 for ( int i = 0 ; i < totalTasks ; i ++ )
38- tasks . Add ( ExecuteWithThrottleAsync ( semaphore , ( ) => taskFactory ( i ) ) ) ;
59+ {
60+ var index = i ; // Capture for closure
61+ tasks . Add ( ExecuteWithThrottleAsync ( semaphore , ( ) => taskFactory ( index ) ) ) ;
62+ }
3963
40- var results = await Task . WhenAll ( tasks ) ;
64+ var results = await Task . WhenAll ( [ .. tasks ] ) ;
4165 return [ .. results . SelectMany ( r => r ) ] ;
4266 }
4367
44- private static async Task < T > ExecuteWithThrottleAsync < T > ( SemaphoreSlim ? semaphore , Func < Task < T > > taskFactory )
68+ private static async Task < List < T > > ExecuteWithThrottleAsync < T > ( SemaphoreSlim semaphore , Func < Task < List < T > > > taskFactory )
4569 {
46- if ( semaphore == null )
47- return await taskFactory ( ) ;
48-
4970 await semaphore . WaitAsync ( ) ;
5071 try
5172 {
0 commit comments