Make WordPress Core

Opened 4 days ago

Last modified 24 hours ago

#65779 new defect (bug)

Speed up register_core_block_style_handles() $register_style check

Reported by: josephscott Owned by:
Priority: normal Milestone: Awaiting Review
Component: General Version:
Severity: normal Keywords: has-patch has-unit-tests
Cc: Focuses: performance

Description

The register_core_block_style_handles() function makes use of a static function $register_style - https://github.com/WordPress/wordpress-develop/blob/trunk/src/wp-includes/blocks/index.php#L97 - which has two in_array() checks.

For both of those in_array() checks there are two conditions that would allow us to swap them for isset() instead. First, the key we are looking for ( $style_path and $rtl_file ) is always a string. Second, we only care to find out if the key exists in the array.

To speed that up we could index $files and use isset() against that index:

$file_index = array_fill_keys( $files, true );
$register_style = static function ( $name, $filename, $style_handle ) use ( $blocks_url, $suffix, $wp_styles, $file_index ) {
...

if ( ! isset( $file_index[ $style_path ] ) ) {

...

if ( is_rtl() && isset( $file_index[ $rtl_file ] ) ) {

...

That saves us from having is_array() needing to walk the entire array looking to a match.

I confirmed that this speeds up register_core_block_style_handles() on my local WordPress 7.0.2 release. I tested by adding hrtime() to the stop and bottom of that function and writing the result with error_log(). Then I requested the Hello World post. This was M5 Macbook Pro.

Median for 10 runs with current is_array() code: 2.434125 ms
Median for 10 runs with isset() code: 1.352646 ms

That is a 44% reduction in how long register_core_block_style_handles() takes to finish. It hooks into init so it runs early and often.

I've got a patch for this and I'm having Claude go through tests to see what the current coverage looks like.

Change History (7)

#1 @josephscott
4 days ago

One other small thing while I'm in here - moving $path = wp_normalize_path( BLOCKS_PATH . $style_path ); to be after the early return condition. It doesn't get used until after the early return, so there is not point in doing that work unless we are actually going to use it.

#2 @khokansardar
4 days ago

  • Focuses performance added

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


4 days ago
#3

  • Keywords has-patch added

register_core_block_style_handles() checked each candidate stylesheet against the core block CSS file list with in_array(). The closure runs three times per core block, so a request walked that 624-entry list roughly 270 times.

What the problem was:

  • Two in_array() scans per closure call, each walking the full file list.
  • wp_normalize_path() ran before the early return, so the result was computed and discarded for every stylesheet that does not exist.

What the fix does:

  • Indexes the file list once with array_fill_keys() and uses isset() for both lookups.
  • Defers wp_normalize_path() until after the early return.

Approach and why:

  • Both lookup keys are always non-numeric strings ending in .css, so key lookup is equivalent to the strict in_array() it replaces. Verified against the real file list: 624 files, 0 keys coerced to integers, 0 lookup mismatches against in_array( ..., true ), including numeric and empty probes.
  • The transient payload is unchanged, so no cache compatibility concern.
  • No new tests: the existing data provider already covers all three changed paths (157 registrations with a path, 188 early returns, 156 RTL variants).

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

## Use of AI Tools

AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Opus 5
Used for: Ticket analysis and tests. All changes were reviewed and validated by me.

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


3 days ago
#4

  • Keywords has-unit-tests added

https://core.trac.wordpress.org/ticket/65779

AI assistance: Yes
Tool(s): Claude
Model(s): Opus 5
Used for: Exploration, validating ideas for improvement, and writing the tests
-->

@mukesh27 commented on PR #12798:


34 hours ago
#5

Thanks for the PR!

Closing in favour of #12802.

@mukesh27 commented on PR #12802:


34 hours ago
#6

Additional props for folks who works on 12798

Props khokansardar, irozum.

#7 @josephscott
24 hours ago

Apologies for the delay on my PR, the power went out for several hours after I submitted this ticket, so I didn't get to the PR until the next day.

Note: See TracTickets for help on using tickets.