throw new Exception( 'Profiling is already enabled.' );
}
self::$enabled = true;
- if ( function_exists( 'xhprof_enable' ) ) {
- xhprof_enable( $flags, $options );
- } elseif ( function_exists( 'tideways_enable' ) ) {
- tideways_enable( $flags, $options );
- } else {
- throw new Exception( "Neither xhprof nor tideways are installed" );
- }
+ self::callAny(
+ [
+ 'xhprof_enable',
+ 'tideways_enable',
+ 'tideways_xhprof_enable'
+ ],
+ [ $flags, $options ]
+ );
}
/**
public static function disable() {
if ( self::isEnabled() ) {
self::$enabled = false;
- if ( function_exists( 'xhprof_disable' ) ) {
- return xhprof_disable();
- } else {
- // tideways
- return tideways_disable();
+ return self::callAny( [
+ 'xhprof_disable',
+ 'tideways_disable',
+ 'tideways_xhprof_disable'
+ ] );
+ }
+ }
+
+ /**
+ * Call the first available function from $functions.
+ * @param array $functions
+ * @param array $args
+ * @throws Exception
+ */
+ protected static function callAny( array $functions, array $args = [] ) {
+ foreach ( $functions as $func ) {
+ if ( function_exists( $func ) ) {
+ return $func( ...$args );
}
}
+
+ throw new Exception( "Neither xhprof nor tideways are installed" );
}
}
* ($wgProfiler['exclude']) containing an array of function names.
* Shell-style patterns are also accepted.
*
- * It is also possible to use the Tideways PHP extension, which is mostly
- * a drop-in replacement for Xhprof. Just change the XHPROF_FLAGS_* constants
- * to TIDEWAYS_FLAGS_*.
+ * This also supports Tideways-XHProf PHP extension, which is mostly a drop-in
+ * replacement for Xhprof (replace XHPROF_FLAGS_* with XHPROF_TIDEWAYS_FLAGS_*),
+ * as well as the older (discontinued) Tideways extension (TIDEWAYS_FLAGS_*).
*
* @copyright © 2014 Wikimedia Foundation and contributors
* @ingroup Profiler
* @see Xhprof
* @see https://php.net/xhprof
* @see https://github.com/facebook/hhvm/blob/master/hphp/doc/profiling.md
- * @see https://github.com/tideways/php-profiler-extension
+ * @see https://github.com/tideways/php-xhprof-extension
*/
class ProfilerXhprof extends Profiler {
/**
$enabled->setValue( true );
$xhprof->getMethod( 'enable' )->invoke( null );
}
+
+ /**
+ * callAny() calls the first function of the list.
+ *
+ * @covers Xhprof::callAny
+ * @dataProvider provideCallAny
+ */
+ public function testCallAny( array $functions, array $args, $expectedResult ) {
+ $xhprof = new ReflectionClass( Xhprof::class );
+ $callAny = $xhprof->getMethod( 'callAny' );
+ $callAny->setAccessible( true );
+
+ $this->assertEquals( $expectedResult,
+ $callAny->invoke( null, $functions, $args ) );
+ }
+
+ /**
+ * Data provider for testCallAny().
+ */
+ public function provideCallAny() {
+ return [
+ [
+ [ 'wfTestCallAny_func1', 'wfTestCallAny_func2', 'wfTestCallAny_func3' ],
+ [ 3, 4 ],
+ 12
+ ],
+ [
+ [ 'wfTestCallAny_nosuchfunc1', 'wfTestCallAny_func2', 'wfTestCallAny_func3' ],
+ [ 3, 4 ],
+ 7
+ ],
+ [
+ [ 'wfTestCallAny_nosuchfunc1', 'wfTestCallAny_nosuchfunc2', 'wfTestCallAny_func3' ],
+ [ 3, 4 ],
+ -1
+ ]
+
+ ];
+ }
+
+ /**
+ * callAny() throws an exception when all functions are unavailable.
+ *
+ * @expectedException Exception
+ * @expectedExceptionMessage Neither xhprof nor tideways are installed
+ * @covers Xhprof::callAny
+ */
+ public function testCallAnyNoneAvailable() {
+ $xhprof = new ReflectionClass( Xhprof::class );
+ $callAny = $xhprof->getMethod( 'callAny' );
+ $callAny->setAccessible( true );
+
+ $callAny->invoke( $xhprof, [
+ 'wfTestCallAny_nosuchfunc1',
+ 'wfTestCallAny_nosuchfunc2',
+ 'wfTestCallAny_nosuchfunc3'
+ ] );
+ }
+}
+
+/** Test function #1 for XhprofTest::testCallAny */
+function wfTestCallAny_func1( $a, $b ) {
+ return $a * $b;
+}
+
+/** Test function #2 for XhprofTest::testCallAny */
+function wfTestCallAny_func2( $a, $b ) {
+ return $a + $b;
+}
+
+/** Test function #3 for XhprofTest::testCallAny */
+function wfTestCallAny_func3( $a, $b ) {
+ return $a - $b;
}