Make WordPress Core

Opened 7 hours ago

Last modified 6 hours ago

#65467 new enhancement

Avoid over-allocation in wp_is_numeric_array()

Reported by: dmsnell's profile dmsnell Owned by:
Milestone: 7.1 Priority: normal
Severity: normal Version: 4.4
Component: General Keywords: has-patch
Focuses: performance Cc:

Description

When a trace of allocations revealed that wp_is_numeric_array() accounted for a significant fraction of the allocations in a page render, it was observed that the function eagerly allocates and copies array keys and then filters them when all it wants to know is whether a single key in the array meets a condition.

This may not have a meaningful impact on performance overall, but it may account for a significant part of the process when parsing theme.json files and removing the allocations and discarded computation is an easy win when this alternative is not meaningfully more complicated than the original code.


Since PHP 8.1 the function array_is_list() is available as well. It performs the probably-intended check that wp_is_numeric_array() performs in practically constant and instant time, also with zero allocation.

There is a subtle difference in behavior, however, in that PHP considers an array a list only if its keys start at zero and increase monotonically. WordPress considers an array numeric if the keys are all numeric keys. It was probably not intentional to draw this distinction, and it’s likely that the impact of a breaking change to defer to the faster built-in PHP function is minimal and worth the change.


This was discovered and discussed and patched during WCEU 2026 Contributor Day.

Change History (3)

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


7 hours ago
#1

  • Keywords has-patch added

Trac ticket: Core-65467

When a trace of allocations revealed that wp_is_numeric_array() accounted for a significant fraction of the allocations in a page render, it was observed that the function eagerly allocates and copies array keys and then filters them when all it wants to know is whether a single key in the array meets a condition.

In this patch the array_filter( array_keys() ) invocation is replaced with early-aborting iteration to avoid the memory allocation and copying.

This patch prepared during WCEU 2026 Contributor Day.

Follow-up to [34927].
Follow-up to 374b39d6ba1dfbffde425e37ca93c59d5b8d5190.

@dmsnell commented on PR #12100:


7 hours ago
#2

it is easy in PHP to turn a list into a numerically-indexed array when using array_filter() in a WP filter, for example. Often I've had to resort to passing arrays through array_values() to turn them into true lists again.

this is a really good point @westonruter, one which I think I’ve run into before and forgot.

encourage devs to use array_is_list() instead

I left a note showing the differences. Now I’m a bit worried that if we try and push people towards array_is_list() we might cause them to overlook the nuance.

Perhaps in a separate PR we could examine returning this, but it’s more work than I want to devote to this right now…

function wp_is_numeric_array( $data ) {
        if ( ! is_array( $data ) ) {
                return false;
        }

        if ( array_is_list( $data ) ) {
                return true;
        }

        foreach ( $data as $key => $value ) {
                if ( is_string( $key ) ) {
                        return false;
                }
        }

        return true;
}

the premise being that the internal speedup for most arrays would outweigh the additional calling cost.

thanks for the instant review!

@westonruter commented on PR #12100:


6 hours ago
#3

(Sorry, I somehow didn't submit those line review comments when I submitted my other comment.)

Note: See TracTickets for help on using tickets.