Repository navigation
perf: Avoid array copies and pass only declared callback arguments - #2
Merged
Merged
Conversation
- Build results by cloning an empty instance and calling exchangeArray(), so the userland constructor no longer makes ArrayObject copy the array - Pass only the arguments a callback declares, delegating to array_map(), array_filter() and array_reduce() when possible - Use array_key_last() on PHP 7.3+ for last()/keyLast() - Add @WarmUp to benchmarks that lacked it, so the one-time autoload cost is not counted - Add unit tests for the callback arity paths
- Add tools/generate-traits.py, the single source of the method traits (supports --check to verify the committed traits are up to date) - Mark generated traits with @generated - Test that pop() and shift() remove the element from the instance
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.
Summary
Follow-up to #1. Brings the library closer to native speed and adds the script that generates the method traits.
Changes
ArrayObjectcopy the whole array, which doubled the cost of every*From()call. Results are now built by cloning an empty instance and callingexchangeArray()(ArrayUtils::blank()).ArrayUtils::callbackArity()). Callbacks that take 1 or 2 arguments usearray_map()/array_filter()/array_reduce()or a loop with fewer arguments; callbacks with 3 or more parameters, variadics, or an undeterminable signature keep the old behavior. As a side effect, internal functions such asstrtoupperwork as callbacks.last()/keyLast()usearray_key_last()on PHP 7.3+ (the oldend()path remains for 7.1/7.2).tools/generate-traits.pyis now the single source of the traits (--checkverifies they are up to date). Generated traits are marked@generated.@WarmuptoFirstLastKeyExistsBenchandUniqueReplaceBench. Without it the one-time autoload cost was counted, which inflated results of those subjects (including some numbers in refactor: Replace magic methods with explicit methods split into feature traits #1).last/keyLast, and thatpop()/shift()remove the element from the instance.Behavior changes
Benchmark:
mainvs this branchPHPBench suite (1000-element arrays,
arrayutilsvariant, mean per call), both sides with the@Warmupfix, run sequentially on the same machine with PHP 8.3. Not run on PHP 7.x.Callback-heavy methods (μs per call; native
array_mapis 23.3,array_reduce-style loop forreduceRightis 25.4):What is left
ArrayObjectcosts about 0.25μs, or about 1μs when the source array is shared (e.g.values()on a list). This only matters where the native call takes under 0.1μs (values,keyRandom,flat,fill,slice,column). The*Asvariants return plain arrays and do not pay it.flatMap0.68 → 0.80μs).Verification
As,From,FromAs) was compared against the previous implementation on 8 inputs and about 1,100 calls; results and instance state matched.vendor/bin/phpunit: 13 tests, 81 assertions pass (PHP 8.3).python3 tools/generate-traits.py --checkreports the traits are up to date.