Skip to content

VM: php bin/vm.php boots in ~1.15 s (2,629 builtin objects, 84 modules, no opcache) and the compliance suite boots it 16,000 times — 2.6 of its 4 hours are startup (script/php-env.sh, lib/ExtensionRegistry.php, test/BaseTest.php) #36206

Description

@PurHur

Category

Foundation: · VM startup / suite runtime · child of #36188

Problem

Measured on this box (master 4eed6a2785):

command wall
php -d auto_prepend_file=vendor/autoload.php -r 'echo "x";' 0.051 s
php bin/vm.php hello.php 1.14–1.26 s
autoloading the 821 ext/standard builtin classes alone 150–165 ms; 53–61 ms with opcache.enable_cli=1 + opcache.file_cache

Causes: ExtensionRegistry::defaultModules() (lib/ExtensionRegistry.php:34) instantiates 84 modules whose getFunctions() new 2,629 builtin objects (828 in ext/standard/Module.php:99 alone), each forcing an autoload of a one-class file; script/php-env.sh:43-53 builds PHP_OPTS with no opcache flags and the image/host have opcache.enable_cli=Off. test/BaseTest.php spawns two processes per case (SKIPIF at :426 and the VM at :497) — 8,114 executed cases × ~1.15 s ≈ 2.6 h of the documented ~4 h serial VMTest. The harness additionally polls with usleep(150000) (:538) so a 20 ms case costs ≥ 150 ms, and drains output only after exit (:542) — a case printing > 64 KB deadlocks on the pipe.

PHP implementation target

  1. script/php-env.sh + BaseTest::phpCommand() + phpc wrapper: add -d opcache.enable_cli=1 -d opcache.file_cache=build/opcache -d opcache.validate_timestamps=0 (key the dir on git SHA) — measured 2.7x on autoload alone.
  2. Lazy builtin registration: generated per-module name → class-string tables; instantiate on first Context::declareFunction/resolveFunctionCallLc; keep the name map authoritative for function_exists, Reflection, get_defined_functions.
  3. Harness: replace the 150 ms poll with stream_select draining; evaluate --SKIPIF-- in-process when it only touches PHPCompiler\* policy classes (945 cases), else spawn; add a bin/vm.php --batch mode (read case paths on stdin, pcntl_fork per case from the warm parent) and route BaseTest::runVmSubprocess through it.
  4. phpunit.xml.dist (1,308 lines, 1,270 explicit <file> entries) → directory suites + PHPT_SHARD/PHPT_SHARDS env so shards can run concurrently in one container.

Repro

./script/docker-exec.sh -- bash -lc 'source script/php-env.sh && printf "<?php echo 1;\n" > build/one.php && time php bin/vm.php build/one.php && time php -d opcache.enable_cli=1 -d opcache.file_cache=/tmp/oc bin/vm.php build/one.php'

Done when

  • php bin/vm.php hello ≤ 0.25 s in the pinned image (step 1+2); included-file count for echo 1 drops ≥ 80 %
  • Serial VMTest ≤ 45 min; 24-shard run ≤ 4 min per shard; failing-name set identical to master's baseline (script/compliance-baseline.sh --diff)
  • A case printing 1 MB no longer hangs; test/compliance/quarantine.txt unchanged

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    MOST IMPORTANTThis are the most important targetsarea:vmVirtual machinebugSomething isn't workingimplementation-readySpec complete: repro, php-src ref, done-when — safe for workers to claimphase-0:FoundationPhase 0 – foundation & DevEx

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions