protected $collateOnly = true;
/** @var array Cache of a standard broken collation entry */
protected $errorEntry;
+ /** @var callable Cache of a profile out callback */
+ protected $profileOutCallback;
/**
* @param array $params
public function __construct( array $params = array() ) {
$this->errorEntry = $this->getErrorEntry();
$this->collateOnly = empty( $params['trace'] );
+ $this->profileOutCallback = function ( $profiler, $section ) {
+ $profiler->profileOutInternal( $section );
+ };
}
/**
public function scopedProfileIn( $section ) {
$this->profileInInternal( $section );
- $that = $this;
- return new ScopedCallback( function () use ( $that, $section ) {
- $that->profileOutInternal( $section );
- } );
+ return new SectionProfileCallback( $this, $section );
}
/**
* @return array List of method entries arrays, each having:
* - name : method name
* - calls : the number of invoking calls
- * - real : real time ellapsed (ms)
+ * - real : real time elapsed (ms)
* - %real : percent real time
- * - cpu : real time ellapsed (ms)
+ * - cpu : real time elapsed (ms)
* - %cpu : percent real time
* - memory : memory used (bytes)
* - %memory : percent memory used
+ * - min_real : min real time in a call (ms)
+ * - max_real : max real time in a call (ms)
*/
public function getFunctionStats() {
$this->collateData();
'%cpu' => $totalCpu ? 100 * $data['cpu'] / $totalCpu : 0,
'memory' => $data['memory'],
'%memory' => $totalMem ? 100 * $data['memory'] / $totalMem : 0,
+ 'min_real' => 1000 * $data['min_real'],
+ 'max_real' => 1000 * $data['max_real']
);
}
'%cpu' => 100,
'memory' => $totalMem,
'%memory' => 100,
+ 'min_real' => 1000 * $totalReal,
+ 'max_real' => 1000 * $totalReal
);
return $profile;
'cpu' => 0.0,
'real' => 0.0,
'memory' => 0,
- 'count' => 0
+ 'count' => 0,
+ 'min_real' => 0.0,
+ 'max_real' => 0.0
);
}
$entry['real'] += $elapsedReal;
$entry['memory'] += $memChange > 0 ? $memChange : 0;
$entry['count']++;
+ $entry['min_real'] = min( $entry['min_real'], $elapsedReal );
+ $entry['max_real'] = max( $entry['max_real'], $elapsedReal );
}
/**
/**
* Returns a tree of function calls with their real times
* @return string
+ * @throws Exception
*/
public function getCallTreeReport() {
if ( $this->collateOnly ) {
}
/**
- * Get the initial time of the request, based either on $wgRequestTime or
- * $wgRUstart. Will return null if not able to find data.
+ * Get the initial time of the request, based on getrusage()
*
* @param string|bool $metric Metric to use, with the following possibilities:
* - user: User CPU time (without system calls)
* - cpu: Total CPU time (user and system calls)
* - wall (or any other string): elapsed time
* - false (default): will fall back to default metric
- * @return float|null
+ * @return float
*/
protected function getTime( $metric = 'wall' ) {
if ( $metric === 'cpu' || $metric === 'user' ) {
}
}
}
+
+/**
+ * Subclass ScopedCallback to avoid call_user_func_array(), which is slow
+ *
+ * This class should not be used outside of SectionProfiler
+ */
+class SectionProfileCallback extends ScopedCallback {
+ /** @var SectionProfiler */
+ protected $profiler;
+ /** @var string */
+ protected $section;
+
+ /**
+ * @param SectionProfiler $profiler
+ * @param string $section
+ */
+ public function __construct( SectionProfiler $profiler, $section ) {
+ parent::__construct( null );
+ $this->profiler = $profiler;
+ $this->section = $section;
+ }
+
+ function __destruct() {
+ $this->profiler->profileOutInternal( $this->section );
+ }
+}