-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Caching inside get_theme_data and get_core_data
#6781
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: trunk
Are you sure you want to change the base?
Caching inside get_theme_data and get_core_data
#6781
Conversation
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the Core Committers: Use this line as a base for the props when committing in SVN: To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
Test using WordPress PlaygroundThe changes in this pull request can previewed and tested using a WordPress Playground instance. WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser. Some things to be aware of
For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation. |
joemcgill
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @kt-12. I think loading the initial theme data from a transient could be a nice improvement, but at present, the potential gains are offset by the fact that transients with an expiration time do not get autoloaded, which results in this PR adding additional DB queries to each request.
Given that we really only need to invalidate the transient if the theme's theme.json data changes, I wonder if we can include a hash of the data just before it's passed to the wp_theme_json_data_theme in the cached data to use for invalidation, instead of the functional args and avoid the transient timeout alltogether?
Aside, this change should happen first in the Gutenberg repo and then get synced back to WP core.
|
|
||
| $can_use_cached = ! wp_is_development_mode( 'theme' ); | ||
| if ( $can_use_cached ) { | ||
| $cache_key = 'get_theme_data_cache_' . md5( wp_json_encode( func_get_args() ) ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think using func_get_args here is necessary, because the theme data get's cached prior to when the with_supports option is calculated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have used $options instead in the new update as we don't quite need other parameters. At the moment set_transient is getting called on every run which is the reason why we don't see any benefit. Comparison of two static variables is not working quite well also other interesting find (off topic) I am able to serialize those variables but not convert into JSON
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@joemcgill You were correct we don't need $options too.
…ub.com/10up/wordpress-develop into enhancement/cache_get_theme_data_57789
joemcgill
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kt-12 I've left a bunch of comments inline, about the specifics of this PR, but overall I have a few concerns:
First, the scope of this PR has now grown well beyond the original purpose, which was to make Theme JSON data from the current theme persistent, and seems to extend it to core data and block data as well. I'm not opposed to trying to add persistence to all three origins, but it does make cache invalidation a bit trickier, which is why we were originally talking about trying to handle these one case at a time—starting with just core and theme data. If there is value in handling all of these cases in the same PR, can you please update the PR title and provide some more context explaining why the scope of the PR has changed?
Second, I think that you can probably simplify a lot of the implementation and instead convert many of the static properties in this class to transients rather than duplicating cached data as a private static property and also as a transient. The easiest way to go about that might be to convert the *_from_persistent_cache() methods to general use get|set_cached_data() methods that populate the static values from persistent cache when $can_use_cached() is true.
Finally, one of the original reasons that these caches were made non-persistent is because it would cause the wp_theme_json_data_default and wp_theme_json_data_theme filters to get skipped. It seems like this approach will still suffer from that problem. I would love to see what the performance benefit would be of storing the theme.json config after it has been processed, but before they are passed to the relevant filters.
| if ( null === static::$theme || ! static::has_same_registered_blocks( 'theme' ) ) { | ||
| $can_use_cached = ! wp_is_development_mode( 'theme' ); | ||
| if ( $can_use_cached ) { | ||
| $cache_key = 'get_theme_data_cache_' . md5( wp_json_encode( $options ) ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still don't think you need to include the options in the cache key here. $options are only used in this function to check for whether theme data should be returned with_supports, meaning whether classic theme theme supports should be merged into the final theme data. However, we're only caching the data from theme.json before it gets merged with theme supports data, so this options shouldn't affect our cache.
| } | ||
|
|
||
| $has_theme_changed = false; | ||
| $has_same_registered_blocks = $can_use_cached ? static::has_same_registered_blocks( 'theme', true ) : static::has_same_registered_blocks( 'theme' ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could be simpler
| $has_same_registered_blocks = $can_use_cached ? static::has_same_registered_blocks( 'theme', true ) : static::has_same_registered_blocks( 'theme' ); | |
| $has_same_registered_blocks = static::has_same_registered_blocks( 'theme', $can_use_cached ); |
| * @return mixed The cache value. | ||
| */ | ||
| private static function get_from_persitent_cache( $cache_key ) { | ||
| if ( null === static::$persistent_all_cache ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The need to back transients with a static cache should be unnecessary because options get saved to the site-options cache after being fetched from the DB so calling get_site_transient() for the same key multiple times during the same pageload should only hit the DB once.
| } | ||
|
|
||
| /** | ||
| * Retrieves persistent cache data of this class for given key. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update docblock description.
| * @return bool True on success, false otherwise. | ||
| */ | ||
| protected static function has_same_registered_blocks( $origin ) { | ||
| protected static function has_same_registered_blocks( $origin, $persistant_cache = false ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Juggling two different caches for registered blocks seems overly complex to me. What if we just converted the static $blocks_cache to an autoloaded transient (no expiration) that only gets used if $can_use_cached is true? We're already validating the cache at the point where this is called by checking the current WP_Block_Type_Registry for all registered blocks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@joemcgill It was a bit of a design decision. I wanted theme data to be checked against the persistent list as we assume the blocks from the theme will not change before the expiry, whereas blocks from user can change dynamically at any instance.
$blocks_cache is just a static cache, and it contains blank arrays of origins in the first call.
If we use the original $blocks_cache the first time has_same_registered_blocks is called, it will always return false as initially $blocks_cache is set to blank arrays, and has_same_registered_blocks sees all blocks as new blocks.
Original has_same_registered_blocks can't be used with persistent cache inside get_theme_data as it will assume the block has changed and will update static::theme, thereby also calling set_site_transient().
Now I can't update $blocks_cache with precipitant value either, w.r.t value of $can_use_cached; as updating
$blocks_cache with persistent value will affect other origins, too, like user or block, which depend on change based on has_same_registered_blocks or not.
Let me check again to see if there is a scope for using just one variable.
| static::$user = null; | ||
| static::$user_custom_post_type_id = null; | ||
| static::$i18n_schema = null; | ||
| delete_persitent_cache(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| delete_persitent_cache(); | |
| static::delete_persitent_cache(); |
| 'theme' => array(), | ||
| 'user' => array(), | ||
| ); | ||
| static::$persistent_blocks_cache = null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we don't backup the persistent cache in a static property of this class, then we can remove this as well.
|
@joemcgill, the ticket's scope is still within what we initially decided. I am only persistently caching My efforts were directed towards maintaining the integrity of One workaround was to call |
get_theme_dataget_theme_data and get_core_data
|
@joemcgill, I have updated this PR with your feedback (I'll shift it to GB shortly). I saw I accidentally pushed 'block' origin cache that I used to get metrics. I have fixed that now.
|
|
@joemcgill GB issue for this task - WordPress/gutenberg#62794 |
|
@joemcgill Putting this on hold. |
Trac ticket: https://core.trac.wordpress.org/ticket/57789
GB PR - WordPress/gutenberg#62794
This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.