Page MenuHomePhabricator

Ensure MediaWiki-Core-Profiler works with php-xhprof 2.x (PHP 8.3)
Closed, ResolvedPublic

Description

Background

The Profiler in MediaWiki core (owned by MPT per mw:Maintainers) is what powers collecting the call graph and memory usage during a request to ease local development (https://www.mediawiki.org/wiki/Manual:Profiling), and in production via WikimediaDebug (https://wikitech.wikimedia.org/wiki/WikimediaDebug#XHGui_profiling).

It has been stable for 10 years and is unlikely to need changes, so this task is mainly to ensure it works on PHP 8.3, and by proxy of testing that, this task is about sharing knowledge inside the platform about how other MW developers use/depend on this, and for team members that haven't used it before, to be famliair with how to install and use it locally.

This task

MediaWiki core supports php-xhprof 0.9 and its fork php-tideways-xhprof. The current version of php-xhprof is 2.x, which we have not tested before. As part of the PHP 8.1 to PHP 8.3 upgrade, we will be switching from the abandoned php-tideways-xhprof package to the php-xhprof 2.x package. I wrote more details and reasons for this package choice at T398245#10965108.

This task represents the MwEng support part of Prep for WMF / 1. Create Debian packages step in the new process (https://wikitech.wikimedia.org/wiki/User:Krinkle/PHP_Upgrade_Process), which is being carried out by SRE in the parent task as part of FY2-26 WE6.4.2: PHP 8.3 upgrade.

Scope

  • Understand and verify status quo
    • On your local dev env with PHP 8.1 and tideways_xhprof, play with $wgProfiler in LocalSettings.php. Documentation: https://www.mediawiki.org/wiki/Manual:Profiling.
    • Generate the "text" output on a page view, which should print a list of function call counts and percentage time spent in an HTML comment
    • Generate the "text" output via a CLI maintenance script.
  • Switch your local dev temporarily to php8.4 and install xhprof from PECL (probably easiest with Quickstart, as opposed to Docker-based dev envs).
  • Generate the same outputs. Or if not working, investigate the upstream changelog, and update the ProfilerXhrof subclass as-needed to ensure it is compatible and outputs the same data as before.
  • Update https://www.mediawiki.org/wiki/Manual:Profiling as-needed with any findings about how to install, enable, and use the feature. In particular, we will now be recommending php-xhprof instead of php-tideways-xhprof, because Tideways has indicated they no longer maintain this (https://github.com/tideways/php-xhprof-extension/).

Details

Other Assignee
matmarex

Related Objects

StatusSubtypeAssignedTask
OpenNone
OpenNone
OpenReedy
OpenNone
OpenNone
OpenNone
OpenNone
OpenNone
OpenNone
OpenKrinkle
ResolvedJdforrester-WMF
ResolvedScott_French
ResolvedScott_French
ResolvedScott_French
ResolvedScott_French
ResolvedScott_French
ResolvedScott_French
ResolvedScott_French
OpenNone
ResolvedKrinkle

Event Timeline

Krinkle updated the task description. (Show Details)
Krinkle updated the task description. (Show Details)

We'll try to get this done this week so that we can unblock the next step in the PHP upgrade process.

Krinkle triaged this task as Medium priority.
Krinkle updated Other Assignee, added: matmarex.
Krinkle added a subscriber: matmarex.

I'm using PHP 8.1 from Homebrew on macOS with MW-Quickstart. The tideways_xhprof extension (https://github.com/tideways/php-xhprof-extension) is not published on pecl.php.net and is not available as a Homebrew package. (Tideways does maintain a Homebrew tap at https://github.com/tideways/homebrew-profiler/, but this is for installing the proprietary php-tideways extension, not the open source php-tideways_xhprof.)

So, I'll install it from source using the instructions in the repository's readme, which provisions tideways_xhprof.so to a directory like /opt/homebrew/Cellar/php@8.1/8.1.XX/pecl/20XX/.

You can set extension=tideways_xhprof.so in your main php.ini to install it globally, or call php -d extension=tideways_xhprof.so instead of php anywhere to use it temporarily. I'll be doing the latter, since I generally want to use Excimer and XHProf, not Tideways.

$ php -d extension=tideways_xhprof.so -i | grep -A10 xhprof
tideways_xhprof

Version => 5.0.4
Clock Source => mach

Tideways is a PHP Profiler, Monitoring and Exception Tracking Software.

Enable tideways_xhprof before restarting composer serve:

--- a/composer.json
+++ b/composer.json
@@ -156,7 +156,7 @@
            "@putenv MW_LOG_DIR=logs",
            "@putenv MW_LOG_STDERR=1",
            "@putenv PHP_CLI_SERVER_WORKERS=8",
-           "@php -S 127.0.0.1:4000"
+           "@php -d extension=tideways_xhprof.so -S 127.0.0.1:4000"
        ],

Enabling $wgProfiler in LocalSettings, based on the docs:

if ( extension_loaded( 'tideways_xhprof' ) ) {
	if ( isset( $_GET['forceprofile'] ) || PHP_SAPI === 'cli' ) {
		$wgProfiler = [
			'class'  => ProfilerXhprof::class,
			'flags'  => TIDEWAYS_XHPROF_FLAGS_CPU | TIDEWAYS_XHPROF_FLAGS_NO_BUILTINS,
			'output' => 'text',
			'thresholdMs' => 0.001, // lower threshold to show stuff on fast requests too
			'running' => true, // profile Setup.php too
		];
		tideways_xhprof_enable( TIDEWAYS_XHPROF_FLAGS_CPU | TIDEWAYS_XHPROF_FLAGS_NO_BUILTINS );
	}
}

Which yields the following at http://localhost:4000/load.php?forceprofile=1

100.00% 0.015      1 - main()
 33.33% 0.005      2 - {closure}
 33.33% 0.005     11 - MediaWiki\MediaWikiServices::getInstance
 33.33% 0.005    594 - AutoLoader::autoload@1
 33.33% 0.005    115 - AutoLoader::autoload

Then, switching back to PHP 8.4:

brew unlink php@8.1
brew link php@8.4

... and installing the latest xhprof from pecl,
... and undoing the local composer.json change,
... and restarting my server.

$ php --version
PHP 8.4.8 (cli) …
$ php -i | grep -A10 xhprof
xhprof

xhprof support => enabled
Version => 2.3.10

Tweaking LocalSettings to use xhprof instead of tideways_xhprof:

if ( extension_loaded( 'xhprof' ) ) {
	if ( isset( $_GET['forceprofile'] ) || PHP_SAPI === 'cli' ) {
		$wgProfiler = [
			'class'  => ProfilerXhprof::class,
			'flags'  => XHPROF_FLAGS_CPU | XHPROF_FLAGS_NO_BUILTINS,
			'output' => 'text',
			'thresholdMs' => 0.001, // lower threshold to show stuff on fast requests too
			'running' => true, // profile Setup.php too
		];
		xhprof_enable( XHPROF_FLAGS_CPU | XHPROF_FLAGS_NO_BUILTINS );
	}
}

We get the following:

100.00% 10.154     1 - main()
 38.32% 3.891      1 - MediaWiki\MediaWikiEntryPoint::run
 38.21% 3.880      1 - MediaWiki\ResourceLoader\ResourceLoaderEntryPoint::execute
  …
 32.55% 3.305      1 - {closure:/Users/krinkle/Development/mediawiki/includes/Setup.php:344}
  …
 21.39% 2.172      1 - MediaWiki\MediaWikiServices::getResourceLoader
  …
 11.87% 1.205      1 - Wikimedia\Services\ServiceContainer::loadWiringFiles
  …
  7.00% 0.711      1 - MediaWiki\ResourceLoader\ResourceLoader::respond
  …
  …
  4.42% 0.449      1 - MediaWiki\Registration\ExtensionRegistry::loadFromQueue
  4.23% 0.430    253 - MediaWiki\ResourceLoader\ResourceLoader::isValidModuleName

Which looks the same, or rather, looks better. It seems for me there was something odd about the measurements in tideways_xhprof (I think it used a unit other than milliseconds, since that PHP 8.1 response was not 0.2ms but 10ms in total, roughly the same as with PHP 8.4).

Works well on the CLI as well.

$ php --version
PHP 8.3.24  …
$ php -i | grep -A1 xhprof
xhprof

xhprof support => enabled
Version => 2.3.10


$ php maintenance/showJobs.php --profiler=text
0
<!--
100.00% 123.587      1 - main()
 53.37% 65.954     70 - MediaWiki\MediaWikiServices::getInstance
 22.40% 27.679      1 - MediaWiki\Maintenance\MaintenanceRunner::run
 21.57% 26.657      1 - ShowJobs::execute

 18.48% 22.845     29 - MediaWiki\JobQueue\JobQueue::getSize
 18.47% 22.821     29 - MediaWiki\JobQueue\JobQueueDB::doGetSize
 15.23% 18.827      1 - MediaWiki\Session\SessionManager::singleton

 11.37% 14.053     29 - MediaWiki\JobQueue\JobQueueDB::getReplicaDB
 11.35% 14.027     29 - MediaWiki\JobQueue\JobQueueDB::getDB
 11.05% 13.652     29 - Wikimedia\Rdbms\DatabaseFactory::create
  6.72% 8.309     29 - Wikimedia\Rdbms\Database::initConnection
  6.67% 8.248     29 - Wikimedia\Rdbms\DatabaseSqlite::open
  6.62% 8.182     87 - Wikimedia\Rdbms\Database::query
  6.25% 7.722     87 - Wikimedia\Rdbms\Database::executeQuery

I've updated the install instructions at https://www.mediawiki.org/wiki/Manual:Profiling to recommend XHProf instead of Tideways going forward, covering various installation methods and distributions.