33using System . Collections . Generic ;
44using System . ComponentModel ;
55using System . Diagnostics ;
6+ using System . Linq ;
67using System . Reflection ;
78using System . Threading ;
89using System . Threading . Tasks ;
@@ -21,12 +22,6 @@ protected const string
2122 SortedSetKey = "myzset" ,
2223 StreamKey = "mystream" ;
2324
24- // how many elements to add for the LRANGE tests
25- protected const int ListElements = 650 ;
26-
27- // how many elements to add for the ZPOPMIN tests
28- protected const int SortedSetElements = 650 ;
29-
3025 public PipelineStrategy PipelineMode { get ; } =
3126 PipelineStrategy . Batch ; // the default, for parity with how redis-benchmark works
3227
@@ -53,9 +48,10 @@ public enum PipelineStrategy
5348 public bool Loop { get ; }
5449 public bool Quiet { get ; }
5550 public int ClientCount { get ; } = 50 ;
56- public int OperationsPerClient { get ; }
51+ private int _operationsPerClient ;
52+ public int OperationsPerClient ( int divisor = 1 ) => _operationsPerClient / divisor ;
5753
58- public int TotalOperations = > OperationsPerClient * ClientCount ;
54+ public int TotalOperations ( int divisor = 1 ) = > OperationsPerClient ( divisor ) * ClientCount ;
5955
6056 protected readonly byte [ ] Payload ;
6157
@@ -119,7 +115,7 @@ protected BenchmarkBase(string[] args)
119115 }
120116 }
121117
122- OperationsPerClient = operations / ClientCount ;
118+ _operationsPerClient = operations / ClientCount ;
123119
124120 Payload = "abc"u8 . ToArray ( ) ;
125121 }
@@ -184,9 +180,10 @@ protected virtual void PrepareBatch(TClient client, int count) { }
184180
185181 private async Task < DBNull > PipelineUntyped (
186182 TClient client ,
187- Func < TClient , ValueTask > operation )
183+ Func < TClient , ValueTask > operation ,
184+ int divisor )
188185 {
189- var opsPerClient = OperationsPerClient ;
186+ var opsPerClient = OperationsPerClient ( divisor ) ;
190187 int i = 0 ;
191188 try
192189 {
@@ -258,9 +255,9 @@ private async Task<DBNull> PipelineUntyped(
258255 return DBNull . Value ;
259256 }
260257
261- private async Task < T > PipelineTyped < T > ( TClient client , Func < TClient , ValueTask < T > > operation )
258+ private async Task < T > PipelineTyped < T > ( TClient client , Func < TClient , ValueTask < T > > operation , int divisor )
262259 {
263- var opsPerClient = OperationsPerClient ;
260+ var opsPerClient = OperationsPerClient ( divisor ) ;
264261 int i = 0 ;
265262 T result = default ! ;
266263 try
@@ -350,31 +347,62 @@ public async Task InitAsync()
350347 protected Task RunAsync < T > (
351348 string ? key ,
352349 Func < TClient , ValueTask < T > > action ,
353- Func < TClient , ValueTask > ? init = null ,
354- string format = "" )
350+ bool deleteKey ,
351+ int divisor = 1 )
355352 => RunAsyncCore < T > (
356353 key ,
357- action ,
354+ GetNameCore ( action , out var desc ) ,
355+ desc ,
356+ client => action ( client ) . AsUntypedValueTask ( ) ,
357+ client => PipelineTyped ( client , action , divisor ) ,
358+ [ ] ,
359+ deleteKey ,
360+ divisor ) ;
361+
362+ protected Task RunAsync < T > (
363+ string ? key ,
364+ Func < TClient , ValueTask < T > > action ,
365+ params string [ ] consumers )
366+ => RunAsyncCore < T > (
367+ key ,
368+ GetNameCore ( action , out var desc ) ,
369+ desc ,
358370 client => action ( client ) . AsUntypedValueTask ( ) ,
359- client => PipelineTyped ( client , action ) ,
360- init ,
361- format ) ;
371+ client => PipelineTyped ( client , action , 1 ) ,
372+ consumers ,
373+ consumers . Length != 0 ,
374+ 1 ) ;
362375
363- // ReSharper disable once UnusedMember.Global
364376 protected Task RunAsync (
365377 string ? key ,
366378 Func < TClient , ValueTask > action ,
367- Func < TClient , ValueTask > ? init = null ,
368- string format = "" )
369- => RunAsyncCore < DBNull > ( key , action , action , client => PipelineUntyped ( client , action ) , init , format ) ;
379+ bool deleteKey ,
380+ int divisor = 1 )
381+ => RunAsyncCore < DBNull > (
382+ key ,
383+ GetNameCore ( action , out var desc ) ,
384+ desc ,
385+ action ,
386+ client => PipelineUntyped ( client , action , divisor ) ,
387+ [ ] ,
388+ deleteKey ,
389+ divisor ) ;
370390
371- private async Task RunAsyncCore < T > (
391+ protected Task RunAsync (
372392 string ? key ,
373- Delegate underlyingAction ,
374- Func < TClient , ValueTask > test ,
375- Func < TClient , Task < T > > pipeline ,
376- Func < TClient , ValueTask > ? init = null ,
377- string format = "" )
393+ Func < TClient , ValueTask > action ,
394+ params string [ ] consumers )
395+ => RunAsyncCore < DBNull > (
396+ key ,
397+ GetNameCore ( action , out var desc ) ,
398+ desc ,
399+ action ,
400+ client => PipelineUntyped ( client , action , 1 ) ,
401+ consumers ,
402+ consumers . Length != 0 ,
403+ 1 ) ;
404+
405+ private static string GetNameCore ( Delegate underlyingAction , out string description )
378406 {
379407 string name = underlyingAction . Method . Name ;
380408
@@ -386,17 +414,44 @@ private async Task RunAsyncCore<T>(
386414 name = dna . DisplayName ;
387415 }
388416
389- // skip test if not needed
390- if ( ! RunTest ( name ) ) return ;
391-
392- // include additional test metadata
393- string description = "" ;
417+ description = "" ;
394418 if ( underlyingAction . Method . GetCustomAttribute ( typeof ( DescriptionAttribute ) ) is DescriptionAttribute
395419 {
396420 Description : { Length : > 0 }
397421 } da )
398422 {
399- description = $ " ({ da . Description } )";
423+ description = da . Description ;
424+ }
425+
426+ return name ;
427+ }
428+
429+ protected static string GetName < T > ( Func < TClient , ValueTask < T > > action ) => GetNameCore ( action , out _ ) ;
430+ protected static string GetName ( Func < TClient , ValueTask > action ) => GetNameCore ( action , out _ ) ;
431+
432+ private async Task RunAsyncCore < T > (
433+ string ? key ,
434+ string name ,
435+ string description ,
436+ Func < TClient , ValueTask > test ,
437+ Func < TClient , Task < T > > pipeline ,
438+ string [ ] consumers ,
439+ bool deleteKey ,
440+ int divisor )
441+ {
442+ // skip test if not needed
443+ string auxReason = "" ;
444+ if ( ! RunTest ( name ) )
445+ {
446+ auxReason = string . Join ( ", " , consumers . Where ( x => RunTest ( x ) ) ) ;
447+ if ( auxReason . Length == 0 ) return ; // not needed by any consumers either
448+ auxReason = $ " (required for { auxReason } )";
449+ }
450+
451+ // include additional test metadata
452+ if ( description is { Length : > 0 } )
453+ {
454+ description = $ " ({ description } )";
400455 }
401456
402457 if ( Quiet )
@@ -406,7 +461,7 @@ private async Task RunAsyncCore<T>(
406461 else
407462 {
408463 Console . Write (
409- $ "====== { name } { description } ====== (clients: { ClientCount : #,##0} , ops: { TotalOperations : #,##0} ") ;
464+ $ "====== { name } { description } { auxReason } ====== (clients: { ClientCount : #,##0} , ops: { TotalOperations ( divisor ) : #,##0} ") ;
410465 if ( Multiplexed )
411466 {
412467 Console . Write ( ", mux" ) ;
@@ -425,7 +480,7 @@ private async Task RunAsyncCore<T>(
425480 bool didNotRun = false ;
426481 try
427482 {
428- if ( key is not null )
483+ if ( key is not null && deleteKey )
429484 {
430485 await DeleteAsync ( GetClient ( 0 ) , key ) . ConfigureAwait ( false ) ;
431486 }
@@ -441,11 +496,6 @@ private async Task RunAsyncCore<T>(
441496 return ;
442497 }
443498
444- if ( init is not null )
445- {
446- await init ( GetClient ( 0 ) ) . ConfigureAwait ( false ) ;
447- }
448-
449499 var pending = new Task < T > [ ClientCount ] ;
450500 int index = 0 ;
451501#if DEBUG
@@ -465,14 +515,17 @@ private async Task RunAsyncCore<T>(
465515 client = CreateBatch ( client ) ;
466516 }
467517
468- pending [ index ++ ] = Task . Run ( ( ) => pipeline ( WithCancellation ( client , cancellationToken ) ) , cancellationToken ) ;
518+ pending [ index ++ ] = Task . Run (
519+ ( ) => pipeline ( WithCancellation ( client , cancellationToken ) ) ,
520+ cancellationToken ) ;
469521 }
470522
471523 await Task . WhenAll ( pending ) . ConfigureAwait ( false ) ;
472524 watch . Stop ( ) ;
473525
474526 var seconds = watch . Elapsed . TotalSeconds ;
475- var rate = TotalOperations / seconds ;
527+ // ReSharper disable once PossibleLossOfFraction
528+ var rate = TotalOperations ( divisor ) / seconds ;
476529 if ( Quiet )
477530 {
478531 Console . WriteLine ( $ "\t { rate : ###,###,##0} requests per second") ;
@@ -481,15 +534,12 @@ private async Task RunAsyncCore<T>(
481534 else
482535 {
483536 Console . WriteLine (
484- $ "{ TotalOperations : ###,###,##0} requests completed in { seconds : 0.00} seconds, { rate : ###,###,##0} ops/sec") ;
537+ $ "{ TotalOperations ( divisor ) : ###,###,##0} requests completed in { seconds : 0.00} seconds, { rate : ###,###,##0} ops/sec") ;
485538 }
486539
487540 if ( ! Quiet & typeof ( T ) != typeof ( DBNull ) )
488541 {
489- if ( string . IsNullOrWhiteSpace ( format ) )
490- {
491- format = "Typical result: {0}" ;
492- }
542+ const string format = "Typical result: {0}" ;
493543
494544 T result = await pending [ ^ 1 ] ;
495545 Console . WriteLine ( format , result ) ;
@@ -575,9 +625,13 @@ private async Task RunAsyncCore<T>(
575625
576626 if ( counters . BatchBufferLeaseCount != 0 | counters . BatchMultiRootMessageCount != 0 )
577627 {
578- Console . Write ( $ "Multi-message batching: { counters . BatchMultiRootMessageCount : #,###,##0} batches, { counters . BatchMultiChildMessageCount : #,###,##0} sub-messages") ;
628+ Console . Write (
629+ $ "Multi-message batching: { counters . BatchMultiRootMessageCount : #,###,##0} batches, { counters . BatchMultiChildMessageCount : #,###,##0} sub-messages") ;
579630 if ( counters . BatchBufferLeaseCount != 0 )
580- Console . Write ( $ "; { counters . BatchBufferLeaseCount : #,###,##0} blocks leased, { counters . BatchBufferReturnCount : #,###,##0} blocks returned, { counters . BatchBufferElementsOutstanding : #,###,##0} elements outstanding") ;
631+ {
632+ Console . Write (
633+ $ "; { counters . BatchBufferLeaseCount : #,###,##0} blocks leased, { counters . BatchBufferReturnCount : #,###,##0} blocks returned, { counters . BatchBufferElementsOutstanding : #,###,##0} elements outstanding") ;
634+ }
581635 Console . WriteLine ( ) ;
582636 }
583637
0 commit comments