Editor, Themes: Evaluate count() once per loop instead of once per iteration - #69
Draft
mukeshpanchal27 wants to merge 16 commits into
Draft
Editor, Themes: Evaluate count() once per loop instead of once per iteration#69mukeshpanchal27 wants to merge 16 commits into
mukeshpanchal27 wants to merge 16 commits into
Conversation
…eration. A `for` condition runs once per iteration plus once to terminate, so `$i < count( $array )` calls `count()` n + 1 times to walk an n-element array whose length never changes. Compute the bound in the loop initialiser instead, matching the idiom already used throughout core. `register_block_type_from_metadata()` is the main beneficiary: it runs for every registered block on every request, and the affected loops sit inside `foreach` blocks covering three script fields and three style fields each. In every case the iterated array is provably invariant across the loop body, so there is no behaviour change. Props mukesh.
…ss-develop into perf/hoist-count
The introduction of a return-type annotation for `absint()` created fatal errors in cases where the function returns a `float` value. This resulted when the value passed into the function is smaller than `PHP_INT_MIN`. Since PHP’s `int` type is unable to represent the magnitude of that number in the positive, it returns a `float` value instead. Reverting the type annotation prevents the crashing, but additional follow-up is warranted to ensure that the function produces the expected return types. Developed in: WordPress#12940 Discussed in: https://core.trac.wordpress.org/ticket/65826 Follow-up to [62647]. Props dmsnell, josephscott, westonruter. Fixes #65826. See #64898. git-svn-id: https://develop.svn.wordpress.org/trunk@63158 602fd350-edb4-49c9-b593-d223f7449a82
… workflows. This commit extends r62891 to the two older reusable PHPUnit workflows. That change added the `runs-on` override to `reusable-phpunit-tests-v3.yml` alone, so only branches calling that workflow can be redirected. Branches 4.7 through 5.1 call `reusable-phpunit-tests-v1.yml`, and branches 5.2 through 5.8 call `reusable-phpunit-tests-v2.yml`, both at `@trunk`. Neither reads the variable, so setting `RUNNERS_NAME` at the repository or organization level has no effect on those twelve branches. This applies the same one-line change to both files. With the variable unset, jobs run on `inputs.os` exactly as before, so there is no change by default. Each of the three reusable PHPUnit workflows contains exactly one `runs-on`, so no other line in these files needs the same treatment. Developed in WordPress#12847. Follow-up to r62891, r62974, r63003. Props lancewillett. Fixes #65749. git-svn-id: https://develop.svn.wordpress.org/trunk@63159 602fd350-edb4-49c9-b593-d223f7449a82
The `$query` variable comes from the `pre_user_query` filter args and is a `WP_User_Query` instance, the `assertInstanceOf( WP_User_Query::class, ... )` on the line above asserts exactly that. The docblock incorrectly declared it as `WP_User`. Developed in WordPress#12834. Follow-up to r59899. Props Soean. See #64894. git-svn-id: https://develop.svn.wordpress.org/trunk@63160 602fd350-edb4-49c9-b593-d223f7449a82
This reverts commit 79d89df.
…ss-develop into perf/hoist-count
Using the dedicated `assertNull()` assertion instead of `assertSame( null, $actual )` clarifies intent and produces more descriptive failure messages. Developed in WordPress#12818. Follow-up to r62969. Props Soean. See #64894. git-svn-id: https://develop.svn.wordpress.org/trunk@63161 602fd350-edb4-49c9-b593-d223f7449a82
Co-authored-by: Weston Ruter <westonruter@gmail.com>
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
A
forloop condition is evaluated once per iteration, plus once more to terminate. When that condition is$i < count( $array ), PHP callscount()n + 1 times to walk an n-element array whose length never changes inside the body.This moves the count into the loop initialiser at the four core sites that still re-evaluate it:
That form is already the dominant idiom in core —
formatting.php:769/:780,class-wp-comment-query.php:1113,class-wpdb.php:3151,functions.php:2106,class-wp-filesystem-base.php:448,image-edit.php:673anddeprecated.php:1741all use it. These were the remaining outliers.Benchmark
100,000 loop runs per row, PHP 8.x:
count()in conditioncount()hoistedTo be clear about what this is and isn't:
count()on a PHP array is O(1) — it reads a cached length — so this is not an algorithmic fix. What it removes is per-iteration function-call overhead (opcode dispatch, frame push, return) repeated n times. Modest per loop, but free, and it makes the fixed bound explicit.Sites changed
src/wp-includes/blocks.phpregister_block_type_from_metadata(), script handles. Runs for every registered block on every request — core alone registers ~100 blocks — and the enclosingforeachcovers three script fields (editorScript,script,viewScript).src/wp-includes/blocks.phpsrc/wp-includes/blocks.phpeditorStyle,style,viewStyle).src/wp-includes/class-wp-theme-json.phpset_spacing_sizes(), relabelling spacing presets.Safety
Hoisting is only valid if the body cannot change the array's length. Each site was checked:
blocks.php(all three) —$scripts,$modulesand$stylesare local copies of a$metadatafield. The body callsregister_block_script_handle()/register_block_script_module_id()/register_block_style_handle()and appends to a separate accumulator ($processed_scriptsetc.). The iterated array is never written to, and the registration helpers receive$metadataby value, so they cannot resize it either.class-wp-theme-json.php— the body assigns$spacing_sizes[ $i ]['name'], overwriting a key on an existing element. It never adds or removes elements, so the count is invariant.No behaviour change: for a fixed-length array,
$i < count( $a )and$i < $cwhere$c = count( $a )are the same condition.Deliberately not changed
formatting.php:3406—wp_targeted_link_rel()has the same pattern with an invariant array, but was deprecated in 6.7.0 and calls_deprecated_function()on entry. Not worth the review surface.for ( $i = count( $x ) - 1; $i >= 0; $i-- )loops —class-wp-http.php:746,html-api/class-wp-html-open-elements.php:645,html-api/class-wp-html-active-formatting-elements.php:200,html-api/class-wp-html-processor.php:944,nav-menu.php:1561,file.php:1630. These callcount()in the initialiser, which already runs exactly once. Nothing to hoist.class-pclzip.phpandrss.php(MagpieRSS) have manysizeof()-in-condition loops, but are vendored libraries core does not maintain.Testing instructions
Results on this branch:
php -l— no syntax errors in either file.phpcs— clean, 0 errors / 0 warnings.This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See Contributing to WordPress for more information.