benchmarks: Report more metrics (min/max/median)
authorTimo Tijhof <krinklemail@gmail.com>
Wed, 19 Apr 2017 23:46:13 +0000 (16:46 -0700)
committerTim Starling <tstarling@wikimedia.org>
Thu, 20 Apr 2017 04:54:32 +0000 (04:54 +0000)
Add minimum, maximum, median to the report in addition to the mean (average)
which was already there. Based on benchmarkTidy.php from I254793fc5.

Example output:

> Delete
>    times: 10
>    total:   7.47ms
>      min:   0.53ms
>   median:   0.74ms
>     mean:   0.75ms
>      max:   1.21ms
>
> Truncate
>    times: 10
>    total:  72.38ms
>      min:   1.37ms
>   median:   8.32ms
>     mean:   7.24ms
>      max:  15.73ms

Change-Id: Ifd3064a3621e07f55505490403189cb47022c6c7

maintenance/benchmarks/Benchmarker.php
maintenance/benchmarks/bench_HTTP_HTTPS.php
maintenance/benchmarks/bench_Wikimedia_base_convert.php
maintenance/benchmarks/bench_delete_truncate.php
maintenance/benchmarks/bench_if_switch.php
maintenance/benchmarks/bench_strtr_str_replace.php
maintenance/benchmarks/bench_utf8_title_check.php
maintenance/benchmarks/bench_wfIsWindows.php

index 7d8280d..638e47e 100644 (file)
@@ -34,7 +34,6 @@ require_once __DIR__ . '/../Maintenance.php';
  * @ingroup Benchmark
  */
 abstract class Benchmarker extends Maintenance {
-       private $results;
        protected $defaultCount = 100;
 
        public function __construct() {
@@ -43,6 +42,7 @@ abstract class Benchmarker extends Maintenance {
        }
 
        public function bench( array $benchs ) {
+               $this->startBench();
                $count = $this->getOption( 'count', $this->defaultCount );
                foreach ( $benchs as $key => $bench ) {
                        // Default to no arguments
@@ -54,11 +54,27 @@ abstract class Benchmarker extends Maintenance {
                        if ( isset( $bench['setup'] ) ) {
                                call_user_func( $bench['setup'] );
                        }
-                       $start = microtime( true );
+
+                       // Run benchmarks
+                       $times = [];
                        for ( $i = 0; $i < $count; $i++ ) {
+                               $t = microtime( true );
                                call_user_func_array( $bench['function'], $bench['args'] );
+                               $t = ( microtime( true ) - $t ) * 1000;
+                               $times[] = $t;
                        }
-                       $delta = microtime( true ) - $start;
+
+                       // Collect metrics
+                       sort( $times, SORT_NUMERIC );
+                       $min = $times[0];
+                       $max = end( $times );
+                       if ( $count % 2 ) {
+                               $median = $times[ ( $count - 1 ) / 2 ];
+                       } else {
+                               $median = ( $times[$count / 2] + $times[$count / 2 - 1] ) / 2;
+                       }
+                       $total = array_sum( $times );
+                       $mean = $total / $count;
 
                        // Name defaults to name of called function
                        if ( is_string( $key ) ) {
@@ -75,35 +91,42 @@ abstract class Benchmarker extends Maintenance {
                                );
                        }
 
-                       $this->results[] = [
+                       $this->addResult( [
                                'name' => $name,
                                'count' => $count,
-                               'total' => $delta,
-                               'average' => $delta / $count,
-                       ];
+                               'total' => $total,
+                               'min' => $min,
+                               'median' => $median,
+                               'mean' => $mean,
+                               'max' => $max,
+                       ] );
                }
        }
 
-       public function getFormattedResults() {
-               $ret = sprintf( "Running PHP version %s (%s) on %s %s %s\n\n",
-                       phpversion(),
-                       php_uname( 'm' ),
-                       php_uname( 's' ),
-                       php_uname( 'r' ),
-                       php_uname( 'v' )
+       public function startBench() {
+               $this->output(
+                       sprintf( "Running PHP version %s (%s) on %s %s %s\n\n",
+                               phpversion(),
+                               php_uname( 'm' ),
+                               php_uname( 's' ),
+                               php_uname( 'r' ),
+                               php_uname( 'v' )
+                       )
                );
-               foreach ( $this->results as $res ) {
-                       // show function with args
-                       $ret .= sprintf( "%s times: %s\n",
-                               $res['count'],
-                               $res['name']
-                       );
-                       $ret .= sprintf( "   %6.2fms (%6.4fms each)\n",
-                               $res['total'] * 1e3,
-                               $res['average'] * 1e3
+       }
+
+       public function addResult( $res ) {
+               $ret = sprintf( "%s\n  %' 6s: %d\n",
+                       $res['name'],
+                       'times',
+                       $res['count']
+               );
+               foreach ( [ 'total', 'min', 'median', 'mean', 'max' ] as $metric ) {
+                       $ret .= sprintf( "  %' 6s: %6.2fms\n",
+                               $metric,
+                               $res[$metric]
                        );
                }
-
-               return $ret;
+               $this->output( "$ret\n" );
        }
 }
index 1be50bd..0e3cd73 100644 (file)
@@ -42,7 +42,6 @@ class BenchHttpHttps extends Benchmarker {
                        [ 'function' => [ $this, 'getHTTP' ] ],
                        [ 'function' => [ $this, 'getHTTPS' ] ],
                ] );
-               $this->output( $this->getFormattedResults() );
        }
 
        private function doRequest( $proto ) {
index bc83a24..86bcc8a 100644 (file)
@@ -60,8 +60,6 @@ class BenchWikimediaBaseConvert extends Benchmarker {
                                'args' => [ $number, $inbase, $outbase, 0, true, 'gmp' ]
                        ],
                ] );
-
-               $this->output( $this->getFormattedResults() );
        }
 
        protected static function makeRandomNumber( $base, $length ) {
index de655b1..0a999ec 100644 (file)
@@ -68,8 +68,6 @@ class BenchmarkDeleteTruncate extends Benchmarker {
                ] );
 
                $dbw->dropTable( 'test' );
-
-               $this->output( $this->getFormattedResults() );
        }
 
        /**
index 32c3932..843ef7c 100644 (file)
@@ -42,7 +42,6 @@ class BenchIfSwitch extends Benchmarker {
                        [ 'function' => [ $this, 'doElseIf' ] ],
                        [ 'function' => [ $this, 'doSwitch' ] ],
                ] );
-               $this->output( $this->getFormattedResults() );
        }
 
        // bench function 1
index 276e666..55c7159 100644 (file)
@@ -51,7 +51,6 @@ class BenchStrtrStrReplace extends Benchmarker {
                        [ 'function' => [ $this, 'benchstrtr_indirect' ] ],
                        [ 'function' => [ $this, 'benchstr_replace_indirect' ] ],
                ] );
-               $this->output( $this->getFormattedResults() );
        }
 
        protected function benchstrtr() {
index 9ba1623..3091de6 100644 (file)
@@ -86,7 +86,6 @@ class BenchUtf8TitleCheck extends Benchmarker {
                        ];
                }
                $this->bench( $benchmarks );
-               $this->output( $this->getFormattedResults() );
        }
 
        protected function use_regexp( $s ) {
index f26dbb2..960ef0e 100644 (file)
@@ -42,7 +42,6 @@ class BenchWfIsWindows extends Benchmarker {
                        [ 'function' => [ $this, 'wfIsWindows' ] ],
                        [ 'function' => [ $this, 'wfIsWindowsCached' ] ],
                ] );
-               print $this->getFormattedResults();
        }
 
        protected static function is_win() {