Skip to content

Start the workers without debuggers and profilers that PHP loads - #9

Merged
ondrejmirtes merged 2 commits into
1.xfrom
strip-profiler-extensions
Nov 14, 2026
Merged

ondrejmirtes merged 2 commits into
1.xfrom
strip-profiler-extensions

Conversation

@ondrejmirtes

Copy link
Copy Markdown
Member

PHP often loads Xdebug, PCOV, and other profilers enabled, and that multiplies the counts. In a loop of method calls, Xdebug in its default develop mode counts 6.5× and PCOV with pcov.enabled=1 3.4×. The workers can't switch them off: they get neither the -d options of tally run nor XDEBUG_MODE, and a setting can't unload an extension. Loaded but switched off (xdebug.mode=off, pcov.enabled=0), they counted exactly what a PHP without them counts.

Stripping

  • When PHP's ini files load one of Configuration::strippedExtensions(), tally run builds a php.ini from them with those lines commented out. The approach follows phpstan-src's restart (IniComposer): each file is cut at its first [PATH=]/[HOST=] section, which CLI never applies, and only the file name counts (tideways-php-8.5.so is Tideways, tideways_xhprof.so is not).
  • Both runs of a case then start with -c <php.ini> and a PHP_INI_SCAN_DIR that doesn't exist, because proc_open leaves out a variable whose value is empty.
  • Without such a line the command line stays the same. The Benchmarks job loads no extension, so the expected numbers don't move.
  • A worker that still loads one, because it's built in or loaded with -d, fails its case instead of counting with it.
  • Default list: xdebug, pcov, uopz, blackfire, tideways, tideways_xhprof, xhprof, spx, excimer, memprof, opentelemetry. withStrippedExtensions() changes it.

E2E tests

The new e2e job runs e2e/stripped-extensions/stripped-extensions_test.sh with bashunit, set up like phpstan-src's e2e tests, in three rows: Xdebug, PCOV, both. With CodSpeed's Valgrind, each test loads the extensions another way: setup-php's scan directory, another scan directory, the php.ini in PHPRC, or -c. It checks that the case doesn't see them and counts within 0.1 % of a PHP without them. Two controls keep the checks from passing for the wrong reason: with withStrippedExtensions([]) the case sees the extensions, and with them loaded by -d the worker refuses to count.

Run locally with Xdebug 3.5.3 and PCOV on PHP 8.5, all three combinations pass. They fail when stripping is switched off, and when the composed ini changes another setting (opcache.enable_cli=1: −27 %).

PHP often loads Xdebug, PCOV, and other profilers enabled, which multiplies
the counts: Xdebug in its default develop mode and PCOV with pcov.enabled=1
count a loop of method calls 6.5 and 3.4 times over. Switching them off does
not reach the workers, which get neither the -d options of tally run nor
XDEBUG_MODE, and a setting cannot unload an extension.

When PHP's ini files load one of Configuration::strippedExtensions(), tally run
composes a php.ini of them with those lines commented out, like the restart of
phpstan-src, and both runs of a case start with -c and a PHP_INI_SCAN_DIR that
does not exist, because proc_open leaves out a variable whose value is empty.
Without such a line, the command line stays as it was, so the expected numbers
of CI do not move. A worker that still loads one fails its case instead of
counting with it.

Amp-Thread-ID: https://ampcode.com/threads/T-01a1dbdd-1694-7100-875a-74f105f1221f
The unit and integration tests run with the fake Valgrind, and only the Code
Coverage and Mutation Testing jobs load an extension to strip, PCOV, which no
test asserts on. The E2E job loads Xdebug, PCOV, or both the way setup-php
does, and the tests load them in other ways on top of it: another scan
directory, the php.ini in PHPRC, and -c. With CodSpeed's Valgrind, the case
must not see them and must count within 0.1 % of a PHP without them, which
also catches a php.ini of the workers that loses another setting. Two
controls keep the checks from passing for the wrong reason: the case sees the
extensions the configuration keeps, and a worker that loads one with -d
refuses to count.

Like the e2e tests of phpstan-src, they are e2e/<name>/<name>_test.sh with a
bootstrap in .bashunitrc, and CI installs bashunit with its pinned action.

Amp-Thread-ID: https://ampcode.com/threads/T-01a1dbdd-1694-7100-875a-74f105f1221f
@ondrejmirtes
ondrejmirtes merged commit 7b37668 into 1.x Nov 14, 2026
30 checks passed
@ondrejmirtes
ondrejmirtes deleted the strip-profiler-extensions branch November 14, 2026 21:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant