benchmarks: Report more metrics (min/max/median)

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
This commit is contained in:
Timo Tijhof 2017-04-19 16:46:13 -07:00 committed by Tim Starling
parent dcc8b7e4ce
commit fa3f8e1fd5
8 changed files with 48 additions and 34 deletions

View 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" );
}
}

View file

@ -42,7 +42,6 @@ class BenchHttpHttps extends Benchmarker {
[ 'function' => [ $this, 'getHTTP' ] ],
[ 'function' => [ $this, 'getHTTPS' ] ],
] );
$this->output( $this->getFormattedResults() );
}
private function doRequest( $proto ) {

View 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 ) {

View file

@ -68,8 +68,6 @@ class BenchmarkDeleteTruncate extends Benchmarker {
] );
$dbw->dropTable( 'test' );
$this->output( $this->getFormattedResults() );
}
/**

View file

@ -42,7 +42,6 @@ class BenchIfSwitch extends Benchmarker {
[ 'function' => [ $this, 'doElseIf' ] ],
[ 'function' => [ $this, 'doSwitch' ] ],
] );
$this->output( $this->getFormattedResults() );
}
// bench function 1

View 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() {

View file

@ -86,7 +86,6 @@ class BenchUtf8TitleCheck extends Benchmarker {
];
}
$this->bench( $benchmarks );
$this->output( $this->getFormattedResults() );
}
protected function use_regexp( $s ) {

View file

@ -42,7 +42,6 @@ class BenchWfIsWindows extends Benchmarker {
[ 'function' => [ $this, 'wfIsWindows' ] ],
[ 'function' => [ $this, 'wfIsWindowsCached' ] ],
] );
print $this->getFormattedResults();
}
protected static function is_win() {