Make WordPress Core

Opened 5 weeks ago

Closed 4 weeks ago

#65811 closed enhancement (fixed)

Hoist count() out of "for" loop conditions

Reported by: mukesh27 Owned by: westonruter
Priority: normal Milestone: 7.2
Component: Editor Version:
Severity: normal Keywords: has-patch commit
Cc: Focuses: performance

Description

A for loop condition is evaluated once per iteration, plus once more to terminate the loop. When that condition is $i < count( $array ), PHP therefore calls count() n + 1 times to walk an n-element array — even though the array size never changes inside the loop body.

The standard fix is to compute the count once in the loop's initialiser:

for ( $i = 0, $c = count( $array ); $i < $c; $i++ )

Change History (9)

#1 @mukesh27
5 weeks ago

  • Owner set to mukesh27
  • Status newassigned

#2 @mukesh27
5 weeks ago

  • Status assignedaccepted

This ticket was mentioned in PR #12837 on WordPress/wordpress-develop by @mukesh27.


5 weeks ago
#3

  • Keywords has-patch added; needs-patch removed

Trac ticket: https://core.trac.wordpress.org/ticket/65811

## Use of AI Tools

AI assistance: Yes
Tool(s): Claude
Model(s): GPT-5.1
Used for: Initial code skeleton and test suggestions; final implementation and tests were reviewed and edited by me.

@afercia commented on PR #12837:


5 weeks ago
#4

Thanks for your PR @mukeshpanchal27
It appears Claude missed something here. I would suggest to consider moving the call to count() outside the loop entirely. With the current approach, for example:

for ( $index = 0, $script_count = count( $scripts ); $index < $script_count; $index++ ) {

there's still one function call per loop iteration, it was just moved to the initialization part.

Instead, moving the count() outside the loop entirely and storing the result in a variable:

  • Eliminates any function calls during loop iterations.
  • Calls count() only once, before the loop starts.
  • Is more readable and clear in intent.
  • Provides maximum performance benefit.
$script_count = count( $scripts );
for ( $index = 0; $index < $script_count; $index++ ) {
    ...

@mukesh27 commented on PR #12837:


5 weeks ago
#5

@afercia Thanks for the feedback it's not addressed. Please take a look when you have moment.

@afercia commented on PR #12837:


5 weeks ago
#6

I don't consider this to be clever code.

In my opinion it's always better to prioritize a more readable and clearer syntax.
It's WordPress. Not a Symfony / Laravel contributor audience. We should always take into consideration the WordPress audience and prioritize ease of contribution.

This whole conversation is a sign that sometimes some syntax isn't immediately understandable. When there's a simpler option, we should use it. In my case, it's in part because of my limitations and that's OK. But I'm not the only one who may find the proposed syntax less readable and understandable.

Between these two options:

Option A:

for ( $index = 0, $length = count( $modules ); $index < $length; $index++ ) {
	// Loop body
}

Option B:

$length = count( $modules );
for ( $index = 0; $index < $length; $index++ ) {
    // Loop body
}

To me, Option B is way clearer.

Not to mention the example with $spacing_sizes_count / $spacing_sizes_length variables names, which is terrible to read:

for ( $spacing_sizes_count = 0, $spacing_sizes_length = count( $spacing_sizes ); $spacing_sizes_count < $spacing_sizes_length; $spacing_sizes_count++ ) {
    // Loop body
}

That said, I'm not married with either of the two syntaxes. I'm still convinced we should strive for simplicity though.

@westonruter commented on PR #12837:


5 weeks ago
#7

@afercia nevertheless, assigning count to a variable in the initializer is standard. It's even on the PHP docs page for for:

https://github.com/user-attachments/assets/196967cc-4246-4226-9594-8cdf24ee2167

https://github.com/user-attachments/assets/270b2d43-bd58-4e96-a2a7-3782719fd813

So I think it is perfectly standard and should be considered simple.

#8 @westonruter
4 weeks ago

  • Keywords commit added
  • Owner changed from mukesh27 to westonruter

#9 @westonruter
4 weeks ago

  • Resolutionfixed
  • Status acceptedclosed

In 63171:

Editor: Hoist count() out of for loop conditions.

A for condition is evaluated once per iteration plus once more to terminate the loop, so $index < count( $scripts ) calls count() n + 1 times to walk an n-element array whose length never changes. Compute the bound once in the loop initializer instead, matching the idiom already used elsewhere in core.

Developed in https://github.com/WordPress/wordpress-develop/pull/12837.
Follow-up to r54155, r57565, r58328.

Props mukesh27, afercia, westonruter.
Fixes #65811.

Note: See TracTickets for help on using tickets.