[wp-trac] [WordPress Trac] #60199: update_menu_item_cache appears to load postmeta for all linked posts
WordPress Trac
noreply at wordpress.org
Sat Jan 6 00:17:26 UTC 2024
#60199: update_menu_item_cache appears to load postmeta for all linked posts
--------------------------+-----------------------------
Reporter: huemordave | Owner: (none)
Type: defect (bug) | Status: new
Priority: normal | Milestone: Awaiting Review
Component: Menus | Version: 6.4.2
Severity: normal | Keywords:
Focuses: performance |
--------------------------+-----------------------------
Discovered this debugging a memory limit error that was causing a staging
site to WSoD on every page. The root cause was that loading the site
header menu triggered loads of all postmeta.
For context, this site has 35 posts in its menu. If I run the query that
killed the site, it returns ~240MB of postmeta (which trips our server's
~512MB memory limit). Yes, 7MB of meta_values per post sounds high; this
is because we use a page builder (Beaver Builder) that stores serialized
post design configuration in postmeta.
While this sounds excessive, it *would* be fine. Except that when
WordPress needs to load menu items (via `wp_get_nav_menu_items`), it
updates a number of related caches. First we update the menu item cache,
then the post cache for any posts that are linked from a menu item, then
the postmeta cache for all the postmeta of those linked posts, then we run
out of memory and crash.
`_prime_post_caches`, the function that updates the post cache, does
provide parameters to enable or disable term and postmeta cache priming.
`update_menu_item_cache` disables term priming but not postmeta priming.
This appears to be an oversight: normal nav menu processing doesn't use
any of the postmeta we're priming the cache with, so there's no point in
loading any of it into the object cache.
The website I diagnosed this problem in is running WordPress 6.4.2 on PHP
8.2. It's hosted on WP Engine which does automatic core and PHP updates.
As part of an earlier diagnosis phase, I disabled every plugin that wasn't
absolutely necessary for rendering this header. I still got the memory
limit error. I was *not* able to disable Beaver Builder or the custom
theme we developed for this client as those are responsible for loading
the template that calls `wp_nav_menu`. I don't think there's any plugin
hooks in Beaver Builder doing anything funny either; I made PHP print out
a stacktrace right before the memory error and the trace goes straight
from my header code to WPDB:
{{{
#0 /wp-includes/class-wpdb.php(2263): wpdb->_do_query('SELECT
post_id,...')
#1 /wp-includes/class-wpdb.php(3152): wpdb->query('SELECT post_id,...')
#2 /wp-includes/meta.php(1177): wpdb->get_results('SELECT post_id,...',
'ARRAY_A')
#3 /wp-includes/post.php(7421): update_meta_cache('post', Array)
#4 /wp-includes/post.php(7808): update_postmeta_cache(Array)
#5 /wp-includes/nav-menu.php(804): _prime_post_caches(Array, false)
#6 /wp-includes/class-wp-query.php(3560): update_menu_item_cache(Array)
#7 /wp-includes/class-wp-query.php(3824): WP_Query->get_posts()
#8 /wp-includes/post.php(2460): WP_Query->query(Array)
#9 /wp-includes/nav-menu.php(729): get_posts(Array)
#10 /wp-includes/nav-menu-template.php(165):
wp_get_nav_menu_items(Object(WP_Term), Array)
#11 /wp-content/themes/beaverwarrior/components/CustomHeader/custom-
header/includes/frontend.php(19): wp_nav_menu(Object(stdClass))
}}}
The way I'm currently fixing this problem is modifying
`update_menu_item_cache`. Yes, this is corehacking, and I understand that
it will be overwritten and break with the next core update.
I specifically changed this line:
{{{#!php
if ( ! empty( $post_ids ) ) {
_prime_post_caches( $post_ids, false );
}
}}}
to instead be:
{{{#!php
if ( ! empty( $post_ids ) ) {
_prime_post_caches( $post_ids, false, false );
}
}}}
This disables postmeta cache priming for linked posts in nav menus and
fixes the memory limit I was running into. I would like to know if there's
any further implications from doing this that I'm not aware of. If not, I
can submit a pull request to have this merged in.
--
Ticket URL: <https://core.trac.wordpress.org/ticket/60199>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform
More information about the wp-trac
mailing list