Summary
prelinked/helper-runtime/x86_64-linux/manifest.json carries a core_fingerprint that no longer
matches the live one. On mismatch every one of the 257 committed units is skipped, so a clean
checkout emits the whole helper corpus live on the first compile.
Measured on master today:
committed core_fingerprint: 34d6fd38281359f382b3
live coreFingerprint(): 63e161964d00f30ff8c9
How it surfaced
The new compiler gate (#24275) failed on a GitHub runner, and the failure is informative:
=== nikic spine preflight (~18s) ===
bootstrap-spine-nikic-preflight: OK 6618/6618 spine PHP files parse
=== AOT smoke ===
FAIL echo compile failed (rc=124)
FAIL arith compile failed (rc=124)
... (all 8 cases, rc=124 = timeout, 120s each)
rc=124 is my 120-second per-case timeout, not a compiler error. A GitHub runner starting from a
clean checkout cannot compile <?php echo "hi\n"; inside two minutes.
This is a real defect, not just a tight timeout
On this dev box the same script passes 8/8 in ~90 s total — because build/helper-runtime-cache is
warm here. That made my local timings unrepresentative of a clean checkout, which is the case a
user actually encounters.
What a fresh clone gets today: the committed cache exists, is skipped wholesale on the fingerprint
mismatch, and the first compile of any script pays for emitting the full corpus. This repo has
measured that cold path at >30 minutes for a trivial script before.
For a project heading to release, "clone and compile hello world" is close to the minimum bar, and
it is currently not met from a clean checkout.
Why it goes stale
The fingerprint covers the lowering machinery (lib/JIT.php, lib/Runtime.php, patches/, …) and
master merges roughly 4 commits/hour with ~56% touching those inputs. So the committed cache is
invalidated within hours of any refresh unless refreshing is part of the routine.
That is the same treadmill RELEASE-PLAN.md Phase 3 describes for gen-0 — an artifact keyed on a
fingerprint that changes several times a day. The difference is that refreshing this one is cheap:
the emit is parallel (PHP_COMPILER_EMIT_JOBS, ~4–5 min for the corpus) rather than the multi-hour
gen-0 rebuild, so it is tractable to keep current.
Suggested fixes
- Refresh the committed cache (
make helper-runtime-prelink-refresh) — I am running this now
and will PR the result with before/after timings.
- Gate on it.
script/check-helper-runtime-prelink.php already exists but is report-only, and
per its own comment an empty glob counts as clean. A fingerprint mismatch should be visible in
release-readiness output rather than silently costing every user a full corpus emit.
- Consider making cold-build time a release criterion — "time to compile hello world from a
clean checkout" is a number worth having in release-readiness --json, because it is exactly
what a new user experiences and nothing currently measures it.
Environment: php-compiler:22.04-dev, PHP 8.2.32, LLVM 9, master 72c379a77.
Summary
prelinked/helper-runtime/x86_64-linux/manifest.jsoncarries acore_fingerprintthat no longermatches the live one. On mismatch every one of the 257 committed units is skipped, so a clean
checkout emits the whole helper corpus live on the first compile.
Measured on master today:
How it surfaced
The new compiler gate (#24275) failed on a GitHub runner, and the failure is informative:
rc=124is my 120-second per-case timeout, not a compiler error. A GitHub runner starting from aclean checkout cannot compile
<?php echo "hi\n";inside two minutes.This is a real defect, not just a tight timeout
On this dev box the same script passes 8/8 in ~90 s total — because
build/helper-runtime-cacheiswarm here. That made my local timings unrepresentative of a clean checkout, which is the case a
user actually encounters.
What a fresh clone gets today: the committed cache exists, is skipped wholesale on the fingerprint
mismatch, and the first compile of any script pays for emitting the full corpus. This repo has
measured that cold path at >30 minutes for a trivial script before.
For a project heading to release, "clone and compile hello world" is close to the minimum bar, and
it is currently not met from a clean checkout.
Why it goes stale
The fingerprint covers the lowering machinery (
lib/JIT.php,lib/Runtime.php,patches/, …) andmaster merges roughly 4 commits/hour with ~56% touching those inputs. So the committed cache is
invalidated within hours of any refresh unless refreshing is part of the routine.
That is the same treadmill RELEASE-PLAN.md Phase 3 describes for gen-0 — an artifact keyed on a
fingerprint that changes several times a day. The difference is that refreshing this one is cheap:
the emit is parallel (
PHP_COMPILER_EMIT_JOBS, ~4–5 min for the corpus) rather than the multi-hourgen-0 rebuild, so it is tractable to keep current.
Suggested fixes
make helper-runtime-prelink-refresh) — I am running this nowand will PR the result with before/after timings.
script/check-helper-runtime-prelink.phpalready exists but is report-only, andper its own comment an empty glob counts as clean. A fingerprint mismatch should be visible in
release-readinessoutput rather than silently costing every user a full corpus emit.clean checkout" is a number worth having in
release-readiness --json, because it is exactlywhat a new user experiences and nothing currently measures it.
Environment:
php-compiler:22.04-dev, PHP 8.2.32, LLVM 9, master72c379a77.