[wp-trac] [WordPress Trac] #62187: Optimize Theme JSON Sanitization for Better Performance Scaling
WordPress Trac
noreply at wordpress.org
Mon Oct 7 23:04:37 UTC 2024
#62187: Optimize Theme JSON Sanitization for Better Performance Scaling
-------------------------+-----------------------------
Reporter: mreishus | Owner: (none)
Type: enhancement | Status: new
Priority: normal | Milestone: Awaiting Review
Component: Themes | Version:
Severity: normal | Keywords:
Focuses: performance |
-------------------------+-----------------------------
This ticket introduces a optimization to the `WP_Theme_JSON::sanitize()`
method to address a performance scaling issue.
== Current Issue ==
The `sanitize()` method's performance is affected by the number of
registered blocks, even when those blocks are unused in the rendered
content. A contributor to this inefficiency is the schema building, which
scales at O(N), where N is the number of registered blocks. This schema is
then built when `sanitize()` is called up to 3 times for each block
rendered, contributing to an overall performance impact that approaches
O(M * N), where M is the number of blocks rendered.
Specifically:
1. The `sanitize()` method builds a `$schema` that includes data for every
possible registered block, regardless of whether it's used in the input.
- It loops over all valid block names, populating
`$schema_settings_blocks` and `$schema_styles_blocks`.
- For each block, it checks for style variations and builds
`$schema_styles_variations`.
- This results in a large, complex schema even for unused blocks.
2. The comprehensive schema is then used in the sanitization process when
calling `static::remove_keys_not_in_schema( $input[ $subtree ], $schema[
$subtree ] );`.
3. Although the `remove_keys_not_in_schema` operation itself is relatively
fast (as it uses direct array key access), the overall process is slowed
by the initial creation of the unnecessarily large `$schema`.
4. As a result, even unused blocks contribute to the processing time,
leading to scaling issues.
== Proposed Solution ==
Our optimization focuses on building only the parts of the schema that we
will actually need before calling the `remove_keys_not_in_schema`
function. Here's how it works:
1. We introduce a new `get_used_blocks()` method to identify which blocks
are actually present in the input data.
2. We then intersect this list of used blocks with the list of valid
blocks.
3. The `$schema` is then built using only these valid, used blocks.
This approach significantly reduces both the time to build the `$schema`
array and its final size in most cases, as it only processes blocks that
are actually used in the input.
== Changes ==
1. Add a new `get_used_blocks()` method to extract block names from the
input.
2. Modify `sanitize()` to build the schema using only the intersection of
valid and used blocks.
== Benefits ==
* Improved performance scaling.
* Reduced unnecessary iterations in the sanitization process.
== Expected Impact ==
This optimization reduces the performance penalty associated with
registering many blocks, allowing for better scalability of block-based
themes and plugins. Our testing methodology and results are as follows:
Testing Method:
- Environment: WordPress site using the Twenty Twenty-Four theme
- Procedure: Visited the home page 10 times for each scenario
- Measurement: Time spent in the sanitize() function
- Result: Median of the 10 measurements
Scenarios and Results:
1. No plugins active (94 blocks registered):
* Before: ~4.50 ms
* After: ~2.52 ms
* Improvement: Approximately 44% faster
2. With WooCommerce active (223 blocks registered):
* Before: ~7.52 ms
* After: ~3.20 ms
* Improvement: Approximately 57% faster
3. With an artificial plugin registering an unusually high number of
blocks (2104 blocks registered):
* Before: ~55 ms
* After: ~11.83 ms
* Improvement: Approximately 78% faster
The improvement is particularly notable for sites using plugins that
register numerous custom blocks, as shown in the third scenario.
Note: Actual performance gains may vary depending on the specific
WordPress setup, server configuration, and other factors.
== Testing ==
Verify that theme JSON sanitization still works correctly for various
inputs.
Benchmark performance improvements, especially for plugins that register
many blocks.
I was using:
{{{
./vendor/bin/phpunit --filter Tests_Block_Template ; ./vendor/bin/phpunit
--filter Tests_Interactivity_API_wpInteractivityAPIFunctions ;
./vendor/bin/phpunit --filter Tests_Theme_wpThemeJson ;
./vendor/bin/phpunit --filter WP_REST_Global_Styles_Controller_Test
}}}
But obviously all unit tests are important. :)
Performance testing should focus on measuring the time taken by the
`sanitize()` method under various scenarios.
This change maintains the integrity of the sanitization process while
providing performance improvements, especially for complex WordPress
setups with many registered blocks.
--
Ticket URL: <https://core.trac.wordpress.org/ticket/62187>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform
More information about the wp-trac
mailing list