Skip to content

Build: no incremental compilation for user projects — every phpc build re-lowers all files as one bundled TU and PHP_COMPILER_CACHE=0 is forced (bin/compile.php, lib/Web/SourceBundler.php, lib/JIT/CompileCache.php) #36199

Description

@PurHur

Category

Foundation: · build speed · child of #36188

Problem

  • SourceBundler::bundleForAot() (lib/Web/SourceBundler.php:25-75) string-concatenates the entry and every include into one source blob → one Script → one Block → one LLVM module. Changing one file of a 200-file app re-lowers 200 files.
  • CompileCache (lib/JIT/CompileCache.php:57-70) — a bitcode cache keyed on (realpath, mtime, sha256(source), fingerprint) — is wired only into Runtime::jit() (lib/Runtime.php:905-940), never into Runtime::standalone() (:956), and bin/compile.php:534 forces PHP_COMPILER_CACHE=0 for user AOT builds (the comment there documents a stale-cache bug rather than fixing the key).
  • Nothing in a user build runs in parallel; the only fan-out in the repo is the cold helper-corpus emitter (script/emit-helper-runtime-object.php:489-560).
  • Warm hello-world build on master 4eed6a2785 is 17 s (README claims ~6 s); MiniWebApp measured separately in the tracker.

The per-unit model that would fix this already exists for helpers (HelperRuntimeCache: fingerprinted unit.o + declarations-only unit.bc + manifest, bound via declareExternFromBitcode). The self-host split-TU work (#36147/#36155) is building the same cross-TU binding for the spine. User builds should be the third consumer of that one mechanism, not a separate design.

PHP implementation target

  1. Cheap first step (M): make standalone() consult CompileCache keyed on sha256(bundled source) + HelperRuntimeCache::coreFingerprint() + helper-index digest + ABI version; restore the module and skip lowering when hit. Delete the PHP_COMPILER_CACHE=0 override once the key includes the helper index.
  2. Per-file TUs (L): lower each include to its own module/object under build/user-object-cache/<sha>/{unit.o,unit.bc,manifest.json}; bind cross-file calls/classes via the split-TU manifest (PHP_COMPILER_EXTERNAL_METHOD_MANIFEST path in lib/AOT/ExternalMethodBind.php); emit unchanged files' objects from cache; emit changed ones in parallel worker processes (reuse the EMIT_JOBS scheduler); one link.
  3. Unbound cross-TU references must be a hard error in this mode (never __value__writeNull, Self-host P0: JIT external class method calls in bundled lib (PhpParser, etc.) #579).
  4. Drop the second new Runtime(MODE_AOT) (bin/compile.php:372 vs :382 — both run loadCoreModules()), and replace path-substring mode detection (phpc_compile_is_user_script_aot, :108-140: selfhost/, compile_driver.php…) with an explicit --mode=user|selfhost|chunk flag so a user project under a selfhost/ directory is not silently compiled with self-host stubs.

Repro

./script/docker-exec.sh -- bash -lc 'source script/php-env.sh && time ./phpc build --project examples/003-MiniWebApp -o build/mw1 \
  && touch examples/003-MiniWebApp/src/Router.php && time ./phpc build --project examples/003-MiniWebApp -o build/mw2'

Today both builds take the same time.

Done when

  • Unchanged-source rebuild of MiniWebApp ≥ 3x faster than a cold one with byte-identical binary (step 1)
  • One-file edit rebuilds in < 25 % of full-build wall (step 2); examples-web-smoke.sh and deploy-smoke.sh green on the incremental binary
  • A fixture at test/fixtures/aot/selfhost/app.php builds as a user script (mode flag) and matches Zend
  • PHP_COMPILER_BUILD_TIMING=json phase report (boot/parse/lower/opt/codegen/link ms) committed for hello-world and MiniWebApp

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

    IMPORTANTCritical patharea:compilerCompiler / CFG / JITenhancementNew feature or requestimplementation-readySpec complete: repro, php-src ref, done-when — safe for workers to claimphase-3:aotPhase 3 – AOT deployment

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions