* @see https://github.com/facebook/hhvm/blob/master/hphp/doc/profiling.md
*/
class ProfilerXhprof extends Profiler {
-
/**
* @var Xhprof $xhprof
*/
protected $xhprof;
+ /**
+ * Profiler for explicit, arbitrary, frame labels
+ * @var SectionProfiler
+ */
+ protected $sprofiler;
+
/**
* Type of report to send when logData() is called.
* @var string $logType
$this->logType = $params['log'];
$this->visible = $params['visible'];
$this->xhprof = new Xhprof( $params );
+ $this->sprofiler = new SectionProfiler();
}
/**
}
public function scopedProfileIn( $section ) {
- static $exists = null;
- // Only HHVM supports this, not the standard PECL extension
- if ( $exists === null ) {
- $exists = function_exists( 'xhprof_frame_begin' );
- }
-
- if ( $exists ) {
- xhprof_frame_begin( $section );
- return new ScopedCallback( function () {
- xhprof_frame_end();
- } );
- }
-
- return new ScopedCallback( function () {
- // no-op
- } );
+ return $this->sprofiler->scopedProfileIn( $section );
}
/**
$metrics = $this->xhprof->getCompleteMetrics();
$profile = array();
+ $main = null; // units in ms
foreach ( $metrics as $fname => $stats ) {
// Convert elapsed times from μs to ms to match ProfilerStandard
- $profile[] = array(
+ $entry = array(
'name' => $fname,
'calls' => $stats['ct'],
'real' => $stats['wt']['total'] / 1000,
'min_real' => $stats['wt']['min'] / 1000,
'max_real' => $stats['wt']['max'] / 1000
);
+ $profile[] = $entry;
+ if ( $fname === 'main()' ) {
+ $main = $entry;
+ }
+ }
+
+ // Merge in all of the custom profile sections
+ foreach ( $this->sprofiler->getFunctionStats() as $stats ) {
+ // @note: getFunctionStats() values already in ms
+ $stats['%real'] = $stats['real'] / $main['real'];
+ $stats['%cpu'] = $main['cpu'] ? $stats['cpu'] / $main['cpu'] * 100 : 0;
+ $stats['%memory'] = $main['memory'] ? $stats['memory'] / $main['memory'] * 100 : 0;
+ $profile[] = $stats; // assume no section names collide with $metrics
}
return $profile;
* - %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 );
}
/**