@@ -14,6 +14,7 @@ public class Benchmarker
1414 private readonly TextWriter _writer ;
1515 private StringBuilder _builder ;
1616 private readonly string _fileOutputPath = null ;
17+ private double _totalMilliseconds = 0 ;
1718
1819 private readonly IDictionary < string , BenchmarkResult > _results = new Dictionary < string , BenchmarkResult > ( ) ;
1920
@@ -42,36 +43,94 @@ public void AddTest(string title, Action test)
4243 _tests . Add ( new BenchmarkItem { Title = title , Test = test } ) ;
4344 }
4445
46+ public void RunTests ( TimeSpan totalTime )
47+ {
48+ RunWarmUp ( 1 ) ;
49+
50+ InternalRun ( null , totalTime ) ;
51+ }
52+
53+ public void RunTests ( int minutes , int seconds )
54+ {
55+ RunTests ( TimeSpan . FromSeconds ( ( minutes * 60 ) + seconds ) ) ;
56+ }
57+
4558 public void RunTests ( int num = 100000 )
4659 {
47- _builder = new StringBuilder ( ) ;
60+ RunWarmUp ( num ) ;
61+
62+ InternalRun ( num , null ) ;
63+ }
4864
65+ private void RunWarmUp ( int totalNum )
66+ {
4967 // WARM-UP
5068 // run thru each of them once because otherwise the first loop is slower due to the Just In Time compilation
51- var numWarmups = Math . Ceiling ( num * WarmUpPercentage ) ;
52-
53- // WriteLine();
54- // WriteLine(String.Format("Running warmup tests {0:#,0} times", numWarmups));
69+ var numWarmups = Math . Ceiling ( totalNum * WarmUpPercentage ) ;
5570
56- for ( var i = 0 ; i < numWarmups ; i ++ )
71+ for ( var i = 0 ; i < numWarmups ; i ++ )
72+ {
5773 foreach ( var test in _tests )
5874 {
5975 test . Test ( ) ;
6076 }
77+ }
78+ }
79+
80+ private void InternalRun ( int ? totalTests , TimeSpan ? totalTime )
81+ {
82+ _builder = new StringBuilder ( ) ;
6183
6284 WriteLine ( ) ;
63- WriteLine ( String . Format ( "Running each test {0:#,0} times" , num ) ) ;
85+
86+ if ( totalTests . HasValue )
87+ {
88+ WriteLine ( String . Format ( "Running each test {0:#,0} times" , totalTests ) ) ;
89+ }
90+ else
91+ {
92+ WriteLine ( String . Format ( "Running tests for {0}" , totalTime ) ) ;
93+ }
94+
6495 WriteLine ( ) ;
6596 WriteLine ( "----------------------------------------------------" ) ;
6697 WriteLine ( "Running tests: " ) ;
6798
68- for ( var i = 0 ; i < _tests . Count ; i ++ )
99+ if ( totalTests . HasValue )
69100 {
70- WriteLine ( String . Format ( " Pass {0}..." , i + 1 ) ) ;
71- InternalRun ( num / _tests . Count ) ;
101+ for ( var i = 0 ; i < _tests . Count ; i ++ )
102+ {
103+ WriteLine ( String . Format ( " Pass {0}..." , i + 1 ) ) ;
104+ InternalSingleRun ( totalTests . Value / _tests . Count ) ;
105+ }
72106 }
73-
107+ else if ( totalTime . HasValue )
108+ {
109+ // the batch size will get adjusted based on how long they are taking to process
110+ // we need to start with 1 and then increase based on their speed
111+ var batchSize = 1 ;
112+ long totalTimesRan = 0 ;
74113
114+ while ( _totalMilliseconds < totalTime . Value . TotalMilliseconds )
115+ {
116+ InternalSingleRun ( batchSize ) ;
117+ totalTimesRan += batchSize ;
118+
119+ // adjust batch size based on the current pace
120+ var percentDone = _totalMilliseconds / totalTime . Value . TotalMilliseconds ;
121+ var estimatedMoreRuns = totalTimesRan / percentDone ;
122+
123+ // let's be safe and try to split it up into a batch for each test so it gets to run in various order
124+ batchSize = ( int ) Math . Floor ( estimatedMoreRuns / _tests . Count + 1 ) ;
125+
126+ WriteLine ( String . Format ( " Running new batch of {0:#,0} tests" , batchSize ) ) ;
127+ }
128+
129+ WriteLine ( ) ;
130+ WriteLine ( String . Format ( " Ran {0:#,0} times in time allotted" , totalTimesRan ) ) ;
131+ WriteLine ( String . Format ( " Took a total of {0}" , TimeSpan . FromMilliseconds ( _totalMilliseconds ) ) ) ;
132+ }
133+
75134 DisplayResults ( ) ;
76135
77136 var resultsText = _builder . ToString ( ) ;
@@ -90,10 +149,10 @@ public void RunTests(int num = 100000)
90149 }
91150 }
92151
93- private void InternalRun ( int num )
152+ private void InternalSingleRun ( int num )
94153 {
95154 var sw = new Stopwatch ( ) ;
96-
155+
97156 foreach ( var benchmarkItem in _tests . OrderBy ( x => Guid . NewGuid ( ) ) )
98157 {
99158 sw . Reset ( ) ;
@@ -132,6 +191,7 @@ private void AddResult(BenchmarkItem item, double totalTime, int timesRun)
132191 var result = _results [ item . Title ] ;
133192 result . TimeRun += timesRun ;
134193 result . TotalTime += totalTime ;
194+ _totalMilliseconds += totalTime ;
135195 }
136196
137197
0 commit comments