Make WordPress Core


Ignore:
Timestamp:
10/11/2022 05:15:11 PM (2 years ago)
Author:
hellofromTonya
Message:

Editor: Fix performance regression in WP_Theme_JSON_Resolver.

A significant performance regression was added late in WP 6.1 beta cycle when some of the existing caching for theme.json processing was removed. The rationale for removing the caching was this code was now used before all the blocks are registered (aka get template data, etc.) and resulted in stale cache that created issues (see Gutenberg Issue 44434 and Gutenberg Issue 44619). The changes were limited to only reads from the file system. However, it introduced a big impact in performance.

This commit adds caching and checks for blocks with different origins. How? It add caching for the calculated data for core, theme, and user based on the blocks that are registered. If the blocks haven't changed since the last time they were calculated for the origin, the cached data is returned. Otherwise, the data is recalculated and cached.

Essentially, this brings back the previous cache, but refreshing it when the blocks change.

It partially adds unit tests for these changes. Additional tests will be added.

References:

Follow-up to [54251], [54399].

Props aristath, oandregal, bernhard-reiter, spacedmonkey, hellofromTonya.
See #56467.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/class-wp-theme-json-resolver.php

    r54491 r54493  
    2222
    2323    /**
     24     * Container for keep track of registered blocks.
     25     *
     26     * @since 6.1.0
     27     * @var array
     28     */
     29    protected static $blocks_cache = array(
     30        'core'   => array(),
     31        'blocks' => array(),
     32        'theme'  => array(),
     33        'user'   => array(),
     34    );
     35
     36    /**
    2437     * Container for data coming from core.
    2538     *
     
    2841     */
    2942    protected static $core = null;
     43
     44    /**
     45     * Container for data coming from the blocks.
     46     *
     47     * @since 6.1.0
     48     * @var WP_Theme_JSON
     49     */
     50    protected static $blocks = null;
    3051
    3152    /**
     
    146167     */
    147168    public static function get_core_data() {
     169        if ( null !== static::$core && static::has_same_registered_blocks( 'core' ) ) {
     170            return static::$core;
     171        }
     172
    148173        $config = static::read_json_file( __DIR__ . '/theme.json' );
    149174        $config = static::translate( $config );
     
    164189
    165190    /**
     191     * Checks whether the registered blocks were already processed for this origin.
     192     *
     193     * @since 6.1.0
     194     *
     195     * @param string $origin Data source for which to cache the blocks.
     196     *                       Valid values are 'core', 'blocks', 'theme', and 'user'.
     197     * @return bool True on success, false otherwise.
     198     */
     199    protected static function has_same_registered_blocks( $origin ) {
     200        // Bail out if the origin is invalid.
     201        if ( ! isset( static::$blocks_cache[ $origin ] ) ) {
     202            return false;
     203        }
     204
     205        $registry = WP_Block_Type_Registry::get_instance();
     206        $blocks   = $registry->get_all_registered();
     207
     208        // Is there metadata for all currently registered blocks?
     209        $block_diff = array_diff_key( $blocks, static::$blocks_cache[ $origin ] );
     210        if ( empty( $block_diff ) ) {
     211            return true;
     212        }
     213
     214        foreach ( $blocks as $block_name => $block_type ) {
     215            static::$blocks_cache[ $origin ][ $block_name ] = true;
     216        }
     217
     218        return false;
     219    }
     220
     221    /**
    166222     * Returns the theme's data.
    167223     *
     
    190246        $options = wp_parse_args( $options, array( 'with_supports' => true ) );
    191247
    192         $theme_json_data = static::read_json_file( static::get_file_path_from_theme( 'theme.json' ) );
    193         $theme_json_data = static::translate( $theme_json_data, wp_get_theme()->get( 'TextDomain' ) );
    194 
    195         /**
    196          * Filters the data provided by the theme for global styles and settings.
    197          *
    198          * @since 6.1.0
    199          *
    200          * @param WP_Theme_JSON_Data Class to access and update the underlying data.
    201          */
    202         $theme_json      = apply_filters( 'theme_json_theme', new WP_Theme_JSON_Data( $theme_json_data, 'theme' ) );
    203         $theme_json_data = $theme_json->get_data();
    204         static::$theme   = new WP_Theme_JSON( $theme_json_data );
     248        if ( null === static::$theme || ! static::has_same_registered_blocks( 'theme' ) ) {
     249            $theme_json_data = static::read_json_file( static::get_file_path_from_theme( 'theme.json' ) );
     250            $theme_json_data = static::translate( $theme_json_data, wp_get_theme()->get( 'TextDomain' ) );
     251
     252            /**
     253             * Filters the data provided by the theme for global styles and settings.
     254             *
     255             * @since 6.1.0
     256             *
     257             * @param WP_Theme_JSON_Data Class to access and update the underlying data.
     258             */
     259            $theme_json      = apply_filters( 'theme_json_theme', new WP_Theme_JSON_Data( $theme_json_data, 'theme' ) );
     260            $theme_json_data = $theme_json->get_data();
     261            static::$theme   = new WP_Theme_JSON( $theme_json_data );
     262        }
    205263
    206264        if ( wp_get_theme()->parent() ) {
     
    259317        $with_theme_supports = new WP_Theme_JSON( $theme_support_data );
    260318        $with_theme_supports->merge( static::$theme );
    261 
    262319        return $with_theme_supports;
    263320    }
     
    273330        $registry = WP_Block_Type_Registry::get_instance();
    274331        $blocks   = $registry->get_all_registered();
    275         $config   = array( 'version' => 2 );
     332
     333        if ( null !== static::$blocks && static::has_same_registered_blocks( 'blocks' ) ) {
     334            return static::$blocks;
     335        }
     336
     337        $config = array( 'version' => 2 );
    276338        foreach ( $blocks as $block_name => $block_type ) {
    277339            if ( isset( $block_type->supports['__experimentalStyle'] ) ) {
     
    299361        $config     = $theme_json->get_data();
    300362
    301         return new WP_Theme_JSON( $config, 'blocks' );
     363        static::$blocks = new WP_Theme_JSON( $config, 'blocks' );
     364        return static::$blocks;
    302365    }
    303366
     
    408471     */
    409472    public static function get_user_data() {
     473        if ( null !== static::$user && static::has_same_registered_blocks( 'user' ) ) {
     474            return static::$user;
     475        }
     476
    410477        $config   = array();
    411478        $user_cpt = static::get_user_data_from_wp_global_styles( wp_get_theme() );
     
    563630     * @since 5.9.0 Added the `$user`, `$user_custom_post_type_id`,
    564631     *              and `$i18n_schema` variables to reset.
     632     * @since 6.1.0 Added the `$blocks` and `$blocks_cache` variables
     633     *              to reset.
    565634     */
    566635    public static function clean_cached_data() {
    567636        static::$core                     = null;
     637        static::$blocks                   = null;
     638        static::$blocks_cache             = array(
     639            'core'   => array(),
     640            'blocks' => array(),
     641            'theme'  => array(),
     642            'user'   => array(),
     643        );
    568644        static::$theme                    = null;
    569645        static::$user                     = null;
Note: See TracChangeset for help on using the changeset viewer.