From eece3f9b92cb9806536b1ba708b39d51b9867037 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 28 Jul 2026 11:15:57 +0200 Subject: [PATCH 1/6] Do not key the container cache on the turbo extension state Reverts 030b59fee3 and the Configurator part of 0587638b4d. In the phar setup the main process does not load the extension and workers get it via -d extension=, so the key differed between them and a single run compiled two containers - undoing 8fd0fdac26 "Do not compile special DI container for workers". The env unsets right above exist to keep main and workers on one container. Nothing in the compiled container depends on the stubs: every shadowed class is a value object or static helper, none is a service, a constructor dependency of one, or named in any conf/*.neon. Once a shadowed class is registered as a service the container does differ, but only by an inert $wiring entry for the stub's native parent class, and main and workers have to share one container anyway - a container that genuinely depended on the stubs cannot be fixed by a cache key. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01EeBk5QAUD6JJecNn6RPYBJ --- src/DependencyInjection/Configurator.php | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/DependencyInjection/Configurator.php b/src/DependencyInjection/Configurator.php index d31fa7e97a..49cc9f546d 100644 --- a/src/DependencyInjection/Configurator.php +++ b/src/DependencyInjection/Configurator.php @@ -11,7 +11,6 @@ use PHPStan\File\CouldNotWriteFileException; use PHPStan\File\FileReader; use PHPStan\File\FileWriter; -use PHPStan\Turbo\TurboExtensionEnabler; use function array_keys; use function count; use function error_reporting; @@ -30,7 +29,6 @@ use function time; use function trim; use function unlink; -use function var_export; use const E_USER_DEPRECATED; use const PHP_RELEASE_VERSION; use const PHP_VERSION_ID; @@ -105,12 +103,6 @@ public function loadContainer(): string is_file($attributesPhp) ? hash_file('sha256', $attributesPhp) : 'attributes-missing', NeonAdapter::CACHE_KEY, $this->getAllConfigFilesHashes(), - // the stubs, not the extension: a shadowed service class is - // reflected while the container compiles, so a container built - // against the stub shells must not be reused by a run that loaded - // the extension but left it inactive (version mismatch, - // PHPSTAN_TURBO=0) and reflects the PHP implementations instead - var_export(TurboExtensionEnabler::isActive(), true), ]; $className = $loader->load( From 71452e191190b717ec396df207afb5ac85086eaf Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 28 Jul 2026 11:51:08 +0200 Subject: [PATCH 2/6] Run the benchmark on PHP 7.4 in addition to PHP 8.5 Both the baseline and the test job are matrixed over PHP 7.4 and 8.5. The 7.4 leg downgrades the source code the same way the test workflow does. phpbench 1.2.14 is the last version that supports PHP 7.4, so that leg pins it, and because it does not have the aggregate-preview report that 'my-report' extends, it uses the built-in 'aggregate' report - its mode column already inlines the percent diff against the baseline. PHPBench attributes are replaced with annotations so that RegressionBench is valid PHP 7.4 - tests/bench is not downgraded, and a multi-line attribute is a syntax error there. That also lets parallel-lint check the file again. Data files that cannot be parsed on the PHP version the benchmark runs on are skipped through the '// lint' comment, the same way TypeInferenceTestCase does it. The baseline is now stored per PHP version. baseline-7.4.xml has to be taken from the phpbench-baseline-7.4 artifact and committed. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01HijxpJYQ5uGfdo6AkXV7TA --- .github/workflows/bench.yml | 62 ++++++++++++++++--- Makefile | 1 - tests/bench/BenchCase.php | 48 ++++++++++++++ tests/bench/RegressionBench.php | 32 ++++++---- tests/bench/data/bug-10772.php | 2 +- tests/bench/data/bug-10979.php | 2 +- tests/bench/data/bug-14869-enum.php | 2 +- .../conditional-expression-infinite-loop.php | 3 +- tests/bench/data/hash-key-lookup.php | 3 +- .../bench/data/in-array-intersect-blowup.php | 3 +- .../{baseline.xml => baseline-8.5.xml} | 0 11 files changed, 131 insertions(+), 27 deletions(-) rename tests/bench/storage/{baseline.xml => baseline-8.5.xml} (100%) diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index d3f3bd0db8..4176a2299f 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -23,10 +23,17 @@ permissions: jobs: baseline: - name: "Baseline" + name: "Baseline (PHP ${{ matrix.php-version }})" runs-on: ubuntu-latest timeout-minutes: 60 + strategy: + fail-fast: false + matrix: + php-version: + - "7.4" + - "8.5" + steps: - name: Harden the runner (Audit all outbound calls) uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 @@ -40,31 +47,56 @@ jobs: uses: "shivammathur/setup-php@7c071dfe9dc99bdf297fa79cb49ea005b9fcadbc" # v2.37.1 with: coverage: "none" - php-version: "8.5" + php-version: "${{ matrix.php-version }}" tools: pecl extensions: ds,mbstring ini-file: development ini-values: memory_limit=-1 + - name: "Downgrade PHPUnit" + if: matrix.php-version == '7.4' + run: "composer require --dev phpunit/phpunit:^9.6 sebastian/diff:^4.0 doctrine/instantiator:^1.0 --update-with-dependencies --ignore-platform-reqs" + - uses: "ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda" # v4.0.0 + + - name: "Downgrade PHPBench" + if: matrix.php-version == '7.4' + run: "composer require --dev phpbench/phpbench:1.2.14 phpunit/phpunit:^9.6 brianium/paratest:^6.5 symfony/console:^5.4 symfony/process:^5.4 doctrine/instantiator:^1.0 --update-with-dependencies --ignore-platform-reqs --working-dir=tests" + - uses: "ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda" # v4.0.0 + if: matrix.php-version != '7.4' with: working-directory: "tests/" + - uses: ./.github/actions/downgrade-code + with: + php-version: "${{ matrix.php-version }}" + - name: "Run phpbench baseline" - run: "tests/vendor/bin/phpbench run --dump-file=tests/bench/storage/baseline.xml --ansi" + run: "tests/vendor/bin/phpbench run --dump-file=tests/bench/storage/baseline-${{ matrix.php-version }}.xml --ansi" - name: "Upload baseline artifact" uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: - name: phpbench-baseline - path: tests/bench/storage/baseline.xml + name: phpbench-baseline-${{ matrix.php-version }} + path: tests/bench/storage/baseline-${{ matrix.php-version }}.xml test: - name: "Test" + name: "Test (PHP ${{ matrix.php-version }})" runs-on: ubuntu-latest timeout-minutes: 60 + strategy: + fail-fast: false + matrix: + include: + # phpbench 1.2.14 is the last version supporting PHP 7.4 + # and it does not have the aggregate-preview report 'my-report' extends + - php-version: "7.4" + report: "aggregate" + - php-version: "8.5" + report: "my-report" + steps: - name: Harden the runner (Audit all outbound calls) uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 @@ -78,16 +110,30 @@ jobs: uses: "shivammathur/setup-php@7c071dfe9dc99bdf297fa79cb49ea005b9fcadbc" # v2.37.1 with: coverage: "none" - php-version: "8.5" + php-version: "${{ matrix.php-version }}" tools: pecl extensions: ds,mbstring ini-file: development ini-values: memory_limit=-1 + - name: "Downgrade PHPUnit" + if: matrix.php-version == '7.4' + run: "composer require --dev phpunit/phpunit:^9.6 sebastian/diff:^4.0 doctrine/instantiator:^1.0 --update-with-dependencies --ignore-platform-reqs" + - uses: "ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda" # v4.0.0 + + - name: "Downgrade PHPBench" + if: matrix.php-version == '7.4' + run: "composer require --dev phpbench/phpbench:1.2.14 phpunit/phpunit:^9.6 brianium/paratest:^6.5 symfony/console:^5.4 symfony/process:^5.4 doctrine/instantiator:^1.0 --update-with-dependencies --ignore-platform-reqs --working-dir=tests" + - uses: "ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda" # v4.0.0 + if: matrix.php-version != '7.4' with: working-directory: "tests/" + - uses: ./.github/actions/downgrade-code + with: + php-version: "${{ matrix.php-version }}" + - name: "Run phpbench test" - run: "tests/vendor/bin/phpbench run --file=tests/bench/storage/baseline.xml --report=my-report --ansi" + run: "tests/vendor/bin/phpbench run --file=tests/bench/storage/baseline-${{ matrix.php-version }}.xml --report=${{ matrix.report }} --ansi" diff --git a/Makefile b/Makefile index e506d79bcf..bfaaa6b192 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,6 @@ lint: XDEBUG_MODE=off php vendor/bin/parallel-lint --colors \ --exclude tests/PHPStan/Analyser/data \ --exclude tests/bench/data \ - --exclude tests/bench/RegressionBench.php \ --exclude tests/PHPStan/Analyser/nsrt \ --exclude tests/PHPStan/Rules/Methods/data \ --exclude tests/PHPStan/Rules/Functions/data \ diff --git a/tests/bench/BenchCase.php b/tests/bench/BenchCase.php index 779718d72a..755b3f3532 100644 --- a/tests/bench/BenchCase.php +++ b/tests/bench/BenchCase.php @@ -2,10 +2,20 @@ namespace PHPStan\Benchmark; +use LogicException; use PHPStan\Analyser\Analyser; use PHPStan\Analyser\AnalyserResultFinalizer; use PHPStan\Analyser\Error; use PHPStan\Testing\PHPStanTestCaseTrait; +use function fclose; +use function fgets; +use function fopen; +use function preg_match; +use function sprintf; +use function str_contains; +use function str_starts_with; +use function version_compare; +use const PHP_VERSION; abstract class BenchCase { @@ -19,6 +29,44 @@ public static function getAdditionalConfigFiles(): array ]; } + /** + * Data files that cannot be parsed on the current PHP version are not worth + * benchmarking - the analysis stops at the syntax error. + * + * Copy of TypeInferenceTestCase::isFileLintSkipped(), originally from + * https://github.com/php-parallel-lint/PHP-Parallel-Lint/blob/0c2706086ac36dce31967cb36062ff8915fe03f7/bin/skip-linting.php + * + * Copyright (c) 2012, Jakub Onderka + */ + protected static function isFileLintSkipped(string $file): bool + { + $f = @fopen($file, 'r'); + if ($f !== false) { + $firstLine = fgets($f); + if ($firstLine === false) { + return false; + } + + // ignore shebang line + if (str_starts_with($firstLine, '#!')) { + $firstLine = fgets($f); + if ($firstLine === false) { + return false; + } + } + + @fclose($f); + + if (preg_match('~ diff --git a/tests/bench/RegressionBench.php b/tests/bench/RegressionBench.php index bef98a0789..4a0ed2d7ee 100644 --- a/tests/bench/RegressionBench.php +++ b/tests/bench/RegressionBench.php @@ -2,26 +2,30 @@ namespace PHPStan\Benchmark; -use PhpBench\Attributes as Bench; use Symfony\Component\Finder\Finder; -#[Bench\Revs(revs: 1)] -#[Bench\Iterations(iterations: 5)] -#[Bench\Warmup(revs: 1)] -#[Bench\RetryThreshold(retryThreshold: 10.0)] -#[Bench\Assert(expression: ' - (mode(baseline.time.avg) < 100 milliseconds and mode(variant.time.avg) < mode(baseline.time.avg) +/- 50%) - or (mode(baseline.time.avg) >= 100 milliseconds and mode(baseline.time.avg) < 500 milliseconds and mode(variant.time.avg) < mode(baseline.time.avg) +/- 25%) - or (mode(baseline.time.avg) >= 500 milliseconds and mode(baseline.time.avg) < 2000 milliseconds and mode(variant.time.avg) < mode(baseline.time.avg) +/- 20%) - or (mode(baseline.time.avg) >= 2000 milliseconds and mode(variant.time.avg) < mode(baseline.time.avg) +/- 10%) -')] +/** + * PHPBench annotations are used instead of attributes so that the benchmark + * also runs on PHP 7.4 with the downgraded source code, where attributes + * are just comments. + * + * The @Assert expression has to stay on a single line - an annotation value + * cannot span multiple lines. + * + * @Revs(1) + * @Iterations(5) + * @Warmup(1) + * @RetryThreshold(10.0) + * @Assert("(mode(baseline.time.avg) < 100 milliseconds and mode(variant.time.avg) < mode(baseline.time.avg) +/- 50%) or (mode(baseline.time.avg) >= 100 milliseconds and mode(baseline.time.avg) < 500 milliseconds and mode(variant.time.avg) < mode(baseline.time.avg) +/- 25%) or (mode(baseline.time.avg) >= 500 milliseconds and mode(baseline.time.avg) < 2000 milliseconds and mode(variant.time.avg) < mode(baseline.time.avg) +/- 20%) or (mode(baseline.time.avg) >= 2000 milliseconds and mode(variant.time.avg) < mode(baseline.time.avg) +/- 10%)") + */ class RegressionBench extends BenchCase { /** + * @ParamProviders({"provideFiles"}) + * * @param array{string} $params */ - #[Bench\ParamProviders(['provideFiles'])] public function benchRunAnalyse(array $params): void { $this->runAnalyse($params[0]); @@ -42,6 +46,10 @@ private static function findTestDataFilesFromDirectory(string $directory): array $finder->sortByName(true); $files = []; foreach ($finder->files()->name('*.php')->in($directory) as $fileInfo) { + if (self::isFileLintSkipped($fileInfo->getPathname())) { + continue; + } + $files[$fileInfo->getBasename()] = [$fileInfo->getPathname()]; } diff --git a/tests/bench/data/bug-10772.php b/tests/bench/data/bug-10772.php index 76ea079046..e7acb5a768 100644 --- a/tests/bench/data/bug-10772.php +++ b/tests/bench/data/bug-10772.php @@ -1,4 +1,4 @@ -= 8.1 namespace Bug10772; diff --git a/tests/bench/data/bug-10979.php b/tests/bench/data/bug-10979.php index 562d7b4eeb..e244f5a7f2 100644 --- a/tests/bench/data/bug-10979.php +++ b/tests/bench/data/bug-10979.php @@ -1,4 +1,4 @@ -= 8.1 declare(strict_types=1); diff --git a/tests/bench/data/bug-14869-enum.php b/tests/bench/data/bug-14869-enum.php index 21a7768bda..4db97e8cd7 100644 --- a/tests/bench/data/bug-14869-enum.php +++ b/tests/bench/data/bug-14869-enum.php @@ -1,4 +1,4 @@ -= 8.1 namespace Bug14869Enum; diff --git a/tests/bench/data/conditional-expression-infinite-loop.php b/tests/bench/data/conditional-expression-infinite-loop.php index 9dda0d65b1..e4e15a3c39 100644 --- a/tests/bench/data/conditional-expression-infinite-loop.php +++ b/tests/bench/data/conditional-expression-infinite-loop.php @@ -1,4 +1,5 @@ -= 8.0 +declare(strict_types=1); namespace ConditionalExpressionInfiniteLoop; class test diff --git a/tests/bench/data/hash-key-lookup.php b/tests/bench/data/hash-key-lookup.php index d97897f6ab..40410b9c2a 100644 --- a/tests/bench/data/hash-key-lookup.php +++ b/tests/bench/data/hash-key-lookup.php @@ -1,4 +1,5 @@ -= 8.0 +declare(strict_types = 1); namespace BenchHashKeyLookup; diff --git a/tests/bench/data/in-array-intersect-blowup.php b/tests/bench/data/in-array-intersect-blowup.php index 2683e03914..573673f59b 100644 --- a/tests/bench/data/in-array-intersect-blowup.php +++ b/tests/bench/data/in-array-intersect-blowup.php @@ -1,4 +1,5 @@ -= 8.0 +declare(strict_types = 1); namespace BenchInArrayIntersectBlowup; diff --git a/tests/bench/storage/baseline.xml b/tests/bench/storage/baseline-8.5.xml similarity index 100% rename from tests/bench/storage/baseline.xml rename to tests/bench/storage/baseline-8.5.xml From 7747314eab695fd9239b5e038223435a3b02b7dc Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 28 Jul 2026 12:05:58 +0200 Subject: [PATCH 3/6] Fix the benchmark workflow on PHP 7.4 and the annotation docblock The prose in the class docblock mentioned an annotation name, which the annotation reader tried to parse as an actual annotation with a null value. tests/composer.json pins the Composer platform to PHP 8.2, so Composer resolved PHPBench's Symfony dependencies to 6.4 even with --ignore-platform-reqs, and those cannot be parsed on PHP 7.4. Unsetting the platform makes Composer resolve against the real PHP version, which also makes pinning the individual Symfony packages unnecessary. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01HijxpJYQ5uGfdo6AkXV7TA --- .github/workflows/bench.yml | 14 ++++++++++++-- tests/bench/RegressionBench.php | 5 +++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index 4176a2299f..7c075cbacb 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -59,9 +59,14 @@ jobs: - uses: "ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda" # v4.0.0 + # tests/composer.json pins the Composer platform to PHP 8.2, which would make + # Composer resolve PHPBench's Symfony dependencies to versions that cannot + # even be parsed on PHP 7.4. Unsetting it resolves against the real PHP version. - name: "Downgrade PHPBench" if: matrix.php-version == '7.4' - run: "composer require --dev phpbench/phpbench:1.2.14 phpunit/phpunit:^9.6 brianium/paratest:^6.5 symfony/console:^5.4 symfony/process:^5.4 doctrine/instantiator:^1.0 --update-with-dependencies --ignore-platform-reqs --working-dir=tests" + run: | + composer config --unset platform.php --working-dir=tests + composer require --dev phpbench/phpbench:1.2.14 phpunit/phpunit:^9.6 brianium/paratest:^6.5 --update-with-all-dependencies --working-dir=tests - uses: "ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda" # v4.0.0 if: matrix.php-version != '7.4' @@ -122,9 +127,14 @@ jobs: - uses: "ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda" # v4.0.0 + # tests/composer.json pins the Composer platform to PHP 8.2, which would make + # Composer resolve PHPBench's Symfony dependencies to versions that cannot + # even be parsed on PHP 7.4. Unsetting it resolves against the real PHP version. - name: "Downgrade PHPBench" if: matrix.php-version == '7.4' - run: "composer require --dev phpbench/phpbench:1.2.14 phpunit/phpunit:^9.6 brianium/paratest:^6.5 symfony/console:^5.4 symfony/process:^5.4 doctrine/instantiator:^1.0 --update-with-dependencies --ignore-platform-reqs --working-dir=tests" + run: | + composer config --unset platform.php --working-dir=tests + composer require --dev phpbench/phpbench:1.2.14 phpunit/phpunit:^9.6 brianium/paratest:^6.5 --update-with-all-dependencies --working-dir=tests - uses: "ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda" # v4.0.0 if: matrix.php-version != '7.4' diff --git a/tests/bench/RegressionBench.php b/tests/bench/RegressionBench.php index 4a0ed2d7ee..a8929c0bcb 100644 --- a/tests/bench/RegressionBench.php +++ b/tests/bench/RegressionBench.php @@ -9,8 +9,9 @@ * also runs on PHP 7.4 with the downgraded source code, where attributes * are just comments. * - * The @Assert expression has to stay on a single line - an annotation value - * cannot span multiple lines. + * The assertion expression has to stay on a single line - an annotation value + * cannot span multiple lines. Annotation names must not be mentioned anywhere + * else in this docblock either, the annotation reader tries to parse them. * * @Revs(1) * @Iterations(5) From e9ea0d5fdd24b578d9dcfa36b7f79466505fa6b5 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 28 Jul 2026 12:15:45 +0200 Subject: [PATCH 4/6] Add the PHP 7.4 phpbench baseline and check that the baseline exists The baseline comes from the phpbench-baseline-7.4 artifact of the Baseline job. PHPBench does not fail when the file passed to --file does not exist - it warns and runs with an empty baseline, so every assertion passes and the job is green while testing nothing. The test job now checks for the file first. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01HijxpJYQ5uGfdo6AkXV7TA --- .github/workflows/bench.yml | 7 + tests/bench/storage/baseline-7.4.xml | 734 +++++++++++++++++++++++++++ 2 files changed, 741 insertions(+) create mode 100644 tests/bench/storage/baseline-7.4.xml diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index 7c075cbacb..b1dbfe797f 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -145,5 +145,12 @@ jobs: with: php-version: "${{ matrix.php-version }}" + # PHPBench does not fail when the baseline file is missing, it just runs + # with an empty baseline and every assertion passes + - name: "Check that the baseline exists" + run: | + test -f tests/bench/storage/baseline-${{ matrix.php-version }}.xml \ + || (echo "Missing tests/bench/storage/baseline-${{ matrix.php-version }}.xml, download it from the phpbench-baseline-${{ matrix.php-version }} artifact of the Baseline job and commit it." && exit 1) + - name: "Run phpbench test" run: "tests/vendor/bin/phpbench run --file=tests/bench/storage/baseline-${{ matrix.php-version }}.xml --report=${{ matrix.report }} --ansi" diff --git a/tests/bench/storage/baseline-7.4.xml b/tests/bench/storage/baseline-7.4.xml new file mode 100644 index 0000000000..6a2eae3b42 --- /dev/null +++ b/tests/bench/storage/baseline-7.4.xml @@ -0,0 +1,734 @@ + + + + + + Linux + runnervmvrwv9 + 6.17.0-1020-azure + #20~24.04.1-Ubuntu SMP Fri Jun 19 20:09:14 UTC 2026 + x86_64 + + + + 7.4.33 + /etc/php/7.4/cli/php.ini + Core, date, libxml, openssl, pcre, zlib, filter, hash, pcntl, Reflection, SPL, session, standard, sodium, mysqlnd, PDO, xml, amqp, apcu, ast, bcmath, bz2, calendar, ctype, curl, dba, dom, enchant, mbstring, FFI, fileinfo, ftp, gd, gettext, gmp, iconv, igbinary, imagick, imap, intl, json, ldap, exif, memcache, mongodb, msgpack, mysqli, odbc, pdo_dblib, PDO_Firebird, pdo_mysql, PDO_ODBC, pdo_pgsql, pdo_sqlite, pdo_sqlsrv, pgsql, Phar, posix, pspell, readline, shmop, SimpleXML, snmp, soap, sockets, sqlite3, sqlsrv, sysvmsg, sysvsem, sysvshm, tidy, tokenizer, xmlreader, xmlrpc, xmlwriter, xsl, yaml, zip, zmq, memcached, redis, ds, Zend OPcache + + + 1 + + + + 1.06689453125 + 0.46728515625 + 0.17626953125 + + + git + (unnamed branch) + + + + 0.0069141387939453 + 0.10108947753906 + 1.3890266418457 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From b335166054a686e60bce5ccd20a2ae14859f373a Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 28 Jul 2026 13:13:44 +0200 Subject: [PATCH 5/6] Take the PHP 7.4 baseline from a runner of the usual speed The first committed baseline came from a runner that was twice as fast as the one that recorded baseline-8.5.xml - PHP 7.4 measured 2x faster than PHP 8.5, which is not possible. Every variant of the test job then looked like a +100% regression. The replacement comes from a runner whose values match the ones in baseline-8.5.xml. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01HijxpJYQ5uGfdo6AkXV7TA --- .github/workflows/bench.yml | 4 + tests/bench/storage/baseline-7.4.xml | 758 +++++++++++++-------------- 2 files changed, 383 insertions(+), 379 deletions(-) diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index b1dbfe797f..3afac9d2d5 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -80,6 +80,10 @@ jobs: - name: "Run phpbench baseline" run: "tests/vendor/bin/phpbench run --dump-file=tests/bench/storage/baseline-${{ matrix.php-version }}.xml --ansi" + # Before committing an artifact as the new baseline, compare the + # values (md5, file_rw) in it with the ones in the currently committed baseline. + # GitHub runners differ in speed by up to 2x, and a baseline recorded on a fast + # runner makes every later run look like a regression. - name: "Upload baseline artifact" uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: diff --git a/tests/bench/storage/baseline-7.4.xml b/tests/bench/storage/baseline-7.4.xml index 6a2eae3b42..a7f865771a 100644 --- a/tests/bench/storage/baseline-7.4.xml +++ b/tests/bench/storage/baseline-7.4.xml @@ -1,6 +1,6 @@ - + Linux @@ -20,9 +20,9 @@ - 1.06689453125 - 0.46728515625 - 0.17626953125 + 1.18505859375 + 0.65478515625 + 0.2568359375 git @@ -30,9 +30,9 @@ - 0.0069141387939453 - 0.10108947753906 - 1.3890266418457 + 0.0090599060058594 + 0.15711784362793 + 1.9268989562988 @@ -46,683 +46,683 @@ - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + From dfefbac5c744b060cdab40a75c54b982137e3b82 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 28 Jul 2026 13:29:15 +0200 Subject: [PATCH 6/6] Update baseliness --- tests/bench/storage/baseline-7.4.xml | 758 +++++++++++------------ tests/bench/storage/baseline-8.5.xml | 882 +++++++++++++-------------- 2 files changed, 820 insertions(+), 820 deletions(-) diff --git a/tests/bench/storage/baseline-7.4.xml b/tests/bench/storage/baseline-7.4.xml index a7f865771a..c310e5acce 100644 --- a/tests/bench/storage/baseline-7.4.xml +++ b/tests/bench/storage/baseline-7.4.xml @@ -1,6 +1,6 @@ - + Linux @@ -20,9 +20,9 @@ - 1.18505859375 - 0.65478515625 - 0.2568359375 + 0.90576171875 + 0.31591796875 + 0.11474609375 git @@ -30,9 +30,9 @@ - 0.0090599060058594 - 0.15711784362793 - 1.9268989562988 + 0.0081062316894531 + 0.18310546875 + 2.1159648895264 @@ -46,683 +46,683 @@ - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + diff --git a/tests/bench/storage/baseline-8.5.xml b/tests/bench/storage/baseline-8.5.xml index b1730670d8..a294a5872b 100644 --- a/tests/bench/storage/baseline-8.5.xml +++ b/tests/bench/storage/baseline-8.5.xml @@ -1,6 +1,6 @@ - + Linux @@ -20,19 +20,19 @@ - 0.8076171875 - 0.21240234375 - 0.06982421875 + 1.63720703125 + 0.41650390625 + 0.1376953125 git - 2.2.x - 8536a413cf14ebe2ef7babf84d7fca40c6ab3c2f + (unnamed branch) + - 0.0059604644775391 - 0.14996528625488 - 1.816987991333 + 0.0071525573730469 + 0.16903877258301 + 1.9760131835938 @@ -46,793 +46,793 @@ - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + +