Repository navigation
Share whole-variable liveness keys and walk the smaller set - #6990
Merged
Merged
Conversation
… set Every write replacing a whole variable observes and kills the read keys of all its slots, and compileAccesses() copied them into each such write: quadratic in the writes and reads of a variable. They are now built once per variable and shared. Removing them, the markers of a variable and the observed keys from the live set walks the smaller of the two sets, like the per-slot markers already did. Amp-Thread-ID: https://ampcode.com/threads/T-01a1ad6c-dec2-72ff-bbe8-5b3b62746c94
ondrejmirtes
force-pushed
the
faster-literal-key-union-write
branch
from
November 7, 2026 08:14
339d009 to
133b195
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
tests/bench/data/literal-key-union-offset-write.php(1000 ×$b = $a; $b['lN'] = N; echo $b['lN'];with$akeyed by a union of 2000 literals) is one of the slowest benchmarks in the CodSpeed workflow (#6974).VariableLivenessResolver. Every write that replaces the whole variable observes and kills the read keys of all of its slots.compileAccesses()copied all of them into each such write, so 1000 writes × ~2000 keys of$b. Going backwards over the function, each of those writes then looped over all 2000 kill keys and all 1001 marker slots of$b, while the live set at that point holds only a handful of keys. The keys are now built once per variable and shared, which PHP's copy-on-write makes free. Removing keys and markers from the live set, and matching observed keys against it, now walks the smaller of the two sets, the way the per-slot markers already did.markersByNameholds the markers of all slots of a variable, so a whole-variable write removes them in one pass.The commit ports the change to the turbo-ext C++ twin, with the regenerated
VariableLivenessResolver.h.This PR first also memoized
UnionType::hasTemplateOrLateResolvableType(). ec1df78 landed the same memo on 2.3.x, so that commit was dropped in the rebase and the numbers below are against 2.3.x with it.Measurements
Instruction counts from CodSpeed's CPU simulation, using the harness from #6974 on an Amp orb with PHP 8.5.12 (absolute numbers differ slightly from the CI runner's):
Peak memory of literal-key-union-offset-write drops from 475 MB to 240 MB.
Wall clock:
bin/phpstan analyse --debugon literal-key-union-offset-write, level 8 + bleedingEdge, median of 7 interleaved runs per side after one warm-up pair, tmpDir removed before each run (about 0.9 s of each run is building the container), no turbo extension. Amp orb, Intel Xeon @ 2.60 GHz, 16 vCPUs, PHP 8.5.12 NTS: 2.73 s → 2.28 s (−16 %; ranges 2.63–2.95 s and 2.18–2.40 s).Checks
After the rebase:
make tests, with and without the turbo extension loaded (23,561 tests). Both runs have one failure,OverridingMethodRuleConfigPhpTest::testTentativeReturnTypesInPhpVersionRange, which fails the same way on unchanged 2.3.x in this environment.smoke.phpALL OK,signature-parity.phpOK,side-by-side.phpOK.make phpstanis clean.Before the rebase,
turbo-ext/tests/walk-trace.phpwas identical (702,499 trace lines), and the raw analysis output of all 86 bench files was identical to 2.3.x's, both without and with the extension.