MediaWiki REL1_35
Benchmarker.php
Go to the documentation of this file.
1<?php
30use Wikimedia\RunningStat;
31
32// @codeCoverageIgnoreStart
33require_once __DIR__ . '/../Maintenance.php';
34// @codeCoverageIgnoreEnd
35
41abstract class Benchmarker extends Maintenance {
42 protected $defaultCount = 100;
43 private $lang;
44
45 public function __construct() {
46 parent::__construct();
47 $this->addOption( 'count', 'How many times to run a benchmark', false, true );
48 $this->addOption( 'verbose', 'Verbose logging of resource usage', false, false, 'v' );
49 }
50
51 public function bench( array $benchs ) {
52 $this->lang = MediaWikiServices::getInstance()->getLanguageFactory()->getLanguage( 'en' );
53
54 $this->startBench();
55 $count = $this->getOption( 'count', $this->defaultCount );
56 $verbose = $this->hasOption( 'verbose' );
57
58 // Normalise
59 $normBenchs = [];
60 foreach ( $benchs as $key => $bench ) {
61 // Shortcut for simple functions
62 if ( is_callable( $bench ) ) {
63 $bench = [ 'function' => $bench ];
64 }
65
66 // Default to no arguments
67 if ( !isset( $bench['args'] ) ) {
68 $bench['args'] = [];
69 }
70
71 // Name defaults to name of called function
72 if ( is_string( $key ) ) {
73 $name = $key;
74 } else {
75 if ( is_array( $bench['function'] ) ) {
76 $name = get_class( $bench['function'][0] ) . '::' . $bench['function'][1];
77 } else {
78 $name = strval( $bench['function'] );
79 }
80 $name = sprintf( "%s(%s)",
81 $name,
82 implode( ', ', $bench['args'] )
83 );
84 }
85
86 $normBenchs[$name] = $bench;
87 }
88
89 foreach ( $normBenchs as $name => $bench ) {
90 // Optional setup called outside time measure
91 if ( isset( $bench['setup'] ) ) {
92 call_user_func( $bench['setup'] );
93 }
94
95 // Run benchmarks
96 $stat = new RunningStat();
97 for ( $i = 0; $i < $count; $i++ ) {
98 // Setup outside of time measure for each loop
99 if ( isset( $bench['setupEach'] ) ) {
100 $bench['setupEach']();
101 }
102 $t = microtime( true );
103 call_user_func_array( $bench['function'], $bench['args'] );
104 $t = ( microtime( true ) - $t ) * 1000;
105 if ( $verbose ) {
106 $this->verboseRun( $i );
107 }
108 $stat->addObservation( $t );
109 }
110
111 $this->addResult( [
112 'name' => $name,
113 'count' => $stat->getCount(),
114 // Get rate per second from mean (in ms)
115 'rate' => $stat->getMean() == 0 ? INF : ( 1.0 / ( $stat->getMean() / 1000.0 ) ),
116 'total' => $stat->getMean() * $stat->getCount(),
117 'mean' => $stat->getMean(),
118 'max' => $stat->max,
119 'stddev' => $stat->getStdDev(),
120 'usage' => [
121 'mem' => memory_get_usage( true ),
122 'mempeak' => memory_get_peak_usage( true ),
123 ],
124 ] );
125 }
126 }
127
128 public function startBench() {
129 $this->output(
130 sprintf( "Running PHP version %s (%s) on %s %s %s\n\n",
131 phpversion(),
132 php_uname( 'm' ),
133 php_uname( 's' ),
134 php_uname( 'r' ),
135 php_uname( 'v' )
136 )
137 );
138 }
139
140 public function addResult( $res ) {
141 $ret = sprintf( "%s\n %' 6s: %d\n",
142 $res['name'],
143 'count',
144 $res['count']
145 );
146 $ret .= sprintf( " %' 6s: %8.1f/s\n",
147 'rate',
148 $res['rate']
149 );
150 foreach ( [ 'total', 'mean', 'max', 'stddev' ] as $metric ) {
151 $ret .= sprintf( " %' 6s: %8.2fms\n",
152 $metric,
153 $res[$metric]
154 );
155 }
156
157 foreach ( [
158 'mem' => 'Current memory usage',
159 'mempeak' => 'Peak memory usage'
160 ] as $key => $label ) {
161 $ret .= sprintf( "%' 20s: %s\n",
162 $label,
163 $this->lang->formatSize( $res['usage'][$key] )
164 );
165 }
166
167 $this->output( "$ret\n" );
168 }
169
170 protected function verboseRun( $iteration ) {
171 $this->output( sprintf( "#%3d - memory: %-10s - peak: %-10s\n",
172 $iteration,
173 $this->lang->formatSize( memory_get_usage( true ) ),
174 $this->lang->formatSize( memory_get_peak_usage( true ) )
175 ) );
176 }
177
183 protected function loadFile( $file ) {
184 $content = file_get_contents( $file );
185 // Detect GZIP compression header
186 if ( substr( $content, 0, 2 ) === "\037\213" ) {
187 $content = gzdecode( $content );
188 }
189 return $content;
190 }
191}
Base class for benchmark scripts.
__construct()
Default constructor.
verboseRun( $iteration)
addResult( $res)
bench(array $benchs)
loadFile( $file)
Abstract maintenance class for quickly writing and churning out maintenance scripts with minimal effo...
output( $out, $channel=null)
Throw some output to the user.
hasOption( $name)
Checks to see if a particular option was set.
addOption( $name, $description, $required=false, $withArg=false, $shortName=false, $multiOccurrence=false)
Add a parameter to the script.
getOption( $name, $default=null)
Get an option, or return the default.
MediaWikiServices is the service locator for the application scope of MediaWiki.
$content
Definition router.php:76
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.
Definition router.php:42