diff --git a/.github/workflows/performance-tests.yml b/.github/workflows/performance-tests.yml index 17246f7..2351d67 100644 --- a/.github/workflows/performance-tests.yml +++ b/.github/workflows/performance-tests.yml @@ -9,8 +9,10 @@ permissions: jobs: run: runs-on: ${{ matrix.operating-system }} + timeout-minutes: 15 strategy: + fail-fast: false matrix: operating-system: [ ubuntu-latest ] php-version: [ '8.1', '8.2', '8.3', '8.4', '8.5' ] @@ -27,11 +29,24 @@ jobs: with: php-version: ${{ matrix.php-version }} coverage: none - ini-values: opcache.enable_cli=1 + # Keep JIT enabled while avoiding the function-JIT crash in PHPUnit's exporter (#92). + ini-values: opcache.enable_cli=1, opcache.jit=tracing, opcache.jit_buffer_size=256M - name: Check PHP version run: php -v + - name: Verify OPcache and tracing JIT + run: | + php -r ' + $status = opcache_get_status(false); + $jit = $status["jit"] ?? []; + echo json_encode(["opcache_enabled" => $status["opcache_enabled"] ?? false, "jit" => $jit], JSON_PRETTY_PRINT), PHP_EOL; + if (!($status["opcache_enabled"] ?? false) || !($jit["enabled"] ?? false) || !($jit["on"] ?? false) || ($jit["kind"] ?? null) !== 5) { + fwrite(STDERR, "Expected OPcache and tracing JIT to be enabled.\n"); + exit(1); + } + ' + - name: Cache Composer packages id: composer-cache uses: actions/cache@v3 diff --git a/PERFORMANCE.md b/PERFORMANCE.md new file mode 100644 index 0000000..b99a0d4 --- /dev/null +++ b/PERFORMANCE.md @@ -0,0 +1,55 @@ +# Performance testing + +Run the benchmark suite with: + +```sh +composer run-script test-performance +``` + +The manually dispatched **PHP Performance Tests** workflow tests PHP 8.1–8.5 +on Ubuntu. It enables OPcache and tracing JIT explicitly: + +```ini +opcache.enable_cli=1 +opcache.jit=tracing +opcache.jit_buffer_size=256M +``` + +For local benchmarks, put these settings in the CLI `php.ini` used by both +PHPUnit and its child PHP processes. Disable Xdebug and other coverage drivers +when benchmarking. The workflow uses `coverage: none` and verifies that OPcache +and tracing JIT are active before running tests. + +Record the PHP version, operating system, JIT mode, and coverage configuration +when comparing timings. Results using tracing JIT should not be treated as +directly comparable to results collected with a different JIT mode. + +## Why tracing JIT is explicit + +[Issue #92](https://github.com/okapi-web/php-aop/issues/92) tracks a PHP JIT +compiler crash encountered during PHPUnit test discovery. `setup-php` supplies +`opcache.jit=1235` by default; enabling CLI OPcache with coverage disabled +activates that mode, which compiles hot functions. Tracing JIT (`1254`) uses +a different compilation mode. + +The crash was reproduced with PHP 8.5.10 on Linux and Windows. In a PHP 8.5.10 +debug build under WSL, the debugger identified +`SebastianBergmann\Exporter\Exporter::recursiveExport()` as the function being +compiled. The engine failed the `count == 1` assertion in `ir_fix_bb_order()` +at `ext/opcache/jit/ir/ir_gcm.c:944`. PHPUnit calls this exporter while formatting +data-provider arguments, before executing the benchmarks. + +An exporter-only reproduction also fails without loading PHPUnit or AOP. +`sebastian/exporter` is a development dependency here, not a runtime dependency +of the library. This identifies the observed crash; it does not establish that +all application code is unaffected by the underlying PHP engine bug. + +Tracing JIT avoids the observed crash while retaining JIT and OPcache for the +library and benchmarks. This is a test-workflow workaround, not a PHP engine +fix or a requirement for consumers to disable JIT. No application configuration +is changed by the library. + +References: + +- [PHP JIT configuration](https://www.php.net/manual/en/opcache.configuration.php#ini.opcache.jit) +- [setup-php JIT defaults](https://github.com/shivammathur/setup-php#jit-configuration) diff --git a/README.md b/README.md index 9e4d7cf..8d2d6da 100644 --- a/README.md +++ b/README.md @@ -760,6 +760,9 @@ $firstLog = $logs[0]; or - Run `composer run-script test-coverage` +For performance tests and the JIT configuration used by CI, see +[Performance testing](PERFORMANCE.md). + ## Contributing