View Issue Details
| ID | Project | Category | View Status | Date Submitted | Last Update |
|---|---|---|---|---|---|
| 0002440 | Xdebug | Code Coverage | public | 2026-10-07 14:31 | 2026-10-07 14:31 |
| Reporter | DevArchitectMaster | Assigned To | |||
| Priority | high | Severity | major | Reproducibility | always |
| Status | new | Resolution | open | ||
| Summary | 0002440: With UNUSED | DEAD_CODE | BRANCH_CHECK together, each call costs more the more calls the process has already made; stopping cove | ||||
| Description | Xdebug version: 3.5.3, which is not yet listed under Product Version. Also reproduced on 3.4.0. When code coverage is started with XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE | XDEBUG_CC_BRANCH_CHECK, every call to a measured function costs more the more such calls the process has already made. xdebug_stop_code_coverage() (default cleanup) does not reset this, and neither does starting coverage again. The three flags have to be used together. BRANCH_CHECK on its own, and every pair of the three flags, stays flat (see Additional Information). Expected result: Actual result (Xdebug 3.5.3, ms per round, every round does the same work): repro.php lines (UNUSED | DEAD_CODE): repro.php (UNUSED | DEAD_CODE | BRANCH_CHECK): A second run gave 67.85 / 167.60 / 378.58 / 586.65 ms. Xdebug 3.4.0 on the same machine gives 35.76 / 129.18 / 359.04 / 599.47 ms. | ||||
| Steps To Reproduce |
<?php xdebug_set_filter(XDEBUG_FILTER_CODE_COVERAGE, XDEBUG_PATH_INCLUDE, [FILE]); for ($round = 1, $t = 0; $round <= 200; $round++) {
XDEBUG_MODE=coverage php -n -d zend_extension=<path to Xdebug> repro.php lines
| ||||
| Additional Information | php -v: PHP 8.2.12 (cli) (built: Oct 24 2023 21:15:15) (ZTS Visual C++ 2019 x64) Relevant settings: none besides XDEBUG_MODE=coverage. The script was run with php -n, so no php.ini was loaded, and Xdebug was loaded with -d zend_extension=... (official php_xdebug-3.5.3-8.2-ts-vs16-x86_64.dll). It takes all three flags. Only the $flags line of the script was changed; Xdebug 3.5.3, ms per round at rounds 50 / 100 / 150 / 200: BRANCH_CHECK 2.98 / 3.49 / 3.35 / 3.41 BRANCH_CHECK on its own also stays flat on Xdebug 3.4.0 (1.55 / 1.56 / 1.75 / 1.72 ms). All three flags together is exactly the set php-code-coverage passes when branch or path coverage is asked for, so every PHPUnit run with branch coverage is affected. How it shows up in practice: PHPUnit runs a whole test suite in one process and starts and stops coverage around every test, which is the loop above. Because each test makes all later tests slower, the cost of a coverage run grows with the square of the suite. In our suite of 2,680 tests:
We saw the same in CI on GitHub Actions (Ubuntu 24.04, Xdebug 3.5.3 via shivammathur/setup-php). There we observed it through the test suite only and did not run the script above. We now work around it by splitting the suite into several PHP processes and merging the coverage reports afterwards. | ||||
| Tags | No tags attached. | ||||
| Operating System | Microsoft Windows 11 Pro 10.0.26200 (x64), official PHP Windows build 8.2.12 ZTS VS16 | ||||
| PHP Version | 8.2.10-8.2.19 | ||||