[wp-trac] [WordPress Trac] #57373: WP_Query loading posts twice.

WordPress Trac noreply at wordpress.org
Thu Jan 19 12:00:33 UTC 2023


#57373: WP_Query loading posts twice.
--------------------------+---------------------------
 Reporter:  spacedmonkey  |       Owner:  spacedmonkey
     Type:  defect (bug)  |      Status:  reopened
 Priority:  normal        |   Milestone:  6.1.2
Component:  Query         |     Version:  6.1
 Severity:  normal        |  Resolution:
 Keywords:  has-patch     |     Focuses:  performance
--------------------------+---------------------------

Comment (by david.binda):

 Hey Peter! I'm not sure if the post object caches being written regardless
 of whether they are warm or not is the cause of the increased memory
 footprint.

 Let me illustrate the behaviour with an example.

 On my local WordPress installation (using the VVV envrionment) with
 memcached enabled, I can see following behaviour after warming up the
 memcache. All the following code has been executed in a single WP CLI's
 shell.


 {{{
 $ wp shell
 wp> get_post( 1 ); // Warms up the cache.
 wp> global $wp_object_cache;
 wp> $wp_object_cache->cache = []; // Cleans up the in-process cache for
 better readability.
 wp> _prime_post_caches( [ 1 ], false, true ); // Does not populate the
 post meta in-process cache.
 wp> $wp_object_cache->cache
 => array(1) {
   [";m-5D,iJF-
 Mw)[Tyqe0M^sxEU:_xgOC=N&d3Urn[z{d9FI0D0ExTtJ&Q/r}>0#wj:1673948700806564:wp_:posts:1"]=>
   array(2) {
     ["value"]=>
     object(stdClass)#2264 (24) {
       ["ID"]=>
       int(1)
       ["post_author"]=>
       string(1) "1"
       ["post_date"]=>
       string(19) "2022-09-13 14:48:41"
       ["post_date_gmt"]=>
       string(19) "2022-09-13 14:48:41"
       ["post_content"]=>
       string(137) "<!-- wp:paragraph -->
 <p>Welcome to WordPress. This is your first post. Edit or delete it, then
 start writing!</p>
 <!-- /wp:paragraph -->"
       ["post_title"]=>
       string(12) "Hello world!"
       ["post_excerpt"]=>
       string(0) ""
       ["post_status"]=>
       string(7) "publish"
       ["comment_status"]=>
       string(4) "open"
       ["ping_status"]=>
       string(4) "open"
       ["post_password"]=>
       string(0) ""
       ["post_name"]=>
       string(11) "hello-world"
       ["to_ping"]=>
       string(0) ""
       ["pinged"]=>
       string(0) ""
       ["post_modified"]=>
       string(19) "2022-09-13 14:48:41"
       ["post_modified_gmt"]=>
       string(19) "2022-09-13 14:48:41"
       ["post_content_filtered"]=>
       string(0) ""
       ["post_parent"]=>
       int(0)
       ["guid"]=>
       string(30) "http://two.wordpress.test/?p=1"
       ["menu_order"]=>
       int(0)
       ["post_type"]=>
       string(4) "post"
       ["post_mime_type"]=>
       string(0) ""
       ["comment_count"]=>
       string(1) "1"
       ["filter"]=>
       string(3) "raw"
     }
     ["found"]=>
     bool(true)
   }
 }
 }}}

 The in-process cache for the post meta is not populated as the post object
 is already stored in memcache server, however the post object is now
 stored in the in-process cache. Any repeated call to `_prime_post_caches(
 [ 1 ], false, true )` won't bring any meta to the in-process cache, thus
 it is not affecting the consumed memory (it's all due to the result of the
 `_get_non_cached_ids` function call ).

 Just for illustration that there is no further magic down there: Calling
 the `get_post( 1 )` does not affect the in-process cache neither:


 {{{
 wp> $post = get_post(1);
 => object(WP_Post)#2270 (24) {
 ...
 }
 wp> $wp_object_cache->cache
 => array(1) {
   [";m-5D,iJF-
 Mw)[Tyqe0M^sxEU:_xgOC=N&d3Urn[z{d9FI0D0ExTtJ&Q/r}>0#wj:1673948700806564:wp_:posts:1"]=>
   array(2) {
     ["value"]=>
     object(stdClass)#2264 (24) {
       ["ID"]=>
       int(1)
       ["post_author"]=>
       string(1) "1"
       ["post_date"]=>
       string(19) "2022-09-13 14:48:41"
       ["post_date_gmt"]=>
       string(19) "2022-09-13 14:48:41"
       ["post_content"]=>
       string(137) "<!-- wp:paragraph -->
 <p>Welcome to WordPress. This is your first post. Edit or delete it, then
 start writing!</p>
 <!-- /wp:paragraph -->"
       ["post_title"]=>
       string(12) "Hello world!"
       ["post_excerpt"]=>
       string(0) ""
       ["post_status"]=>
       string(7) "publish"
       ["comment_status"]=>
       string(4) "open"
       ["ping_status"]=>
       string(4) "open"
       ["post_password"]=>
       string(0) ""
       ["post_name"]=>
       string(11) "hello-world"
       ["to_ping"]=>
       string(0) ""
       ["pinged"]=>
       string(0) ""
       ["post_modified"]=>
       string(19) "2022-09-13 14:48:41"
       ["post_modified_gmt"]=>
       string(19) "2022-09-13 14:48:41"
       ["post_content_filtered"]=>
       string(0) ""
       ["post_parent"]=>
       int(0)
       ["guid"]=>
       string(30) "http://two.wordpress.test/?p=1"
       ["menu_order"]=>
       int(0)
       ["post_type"]=>
       string(4) "post"
       ["post_mime_type"]=>
       string(0) ""
       ["comment_count"]=>
       string(1) "1"
       ["filter"]=>
       string(3) "raw"
     }
     ["found"]=>
     bool(true)
   }
 }
 }}}


 However, in case I run `update_post_caches` I get the post meta stored in
 the in-process cache, despite the logic you are mentioning in your
 comment:


 {{{
 wp> $posts = [ $post ];
 wp> update_post_caches( $posts, false, true );
 => NULL
 wp> $wp_object_cache->cache
 => array(5) {
   [";m-5D,iJF-
 Mw)[Tyqe0M^sxEU:_xgOC=N&d3Urn[z{d9FI0D0ExTtJ&Q/r}>0#wj:1673948700806564:wp_:posts:1"]=>
   array(2) {
     ["value"]=>
     object(stdClass)#2407 (24) {
       ["ID"]=>
       int(1)
       ["post_author"]=>
       string(1) "1"
       ["post_date"]=>
       string(19) "2022-09-13 14:48:41"
       ["post_date_gmt"]=>
       string(19) "2022-09-13 14:48:41"
       ["post_content"]=>
       string(137) "<!-- wp:paragraph -->
 <p>Welcome to WordPress. This is your first post. Edit or delete it, then
 start writing!</p>
 <!-- /wp:paragraph -->"
       ["post_title"]=>
       string(12) "Hello world!"
       ["post_excerpt"]=>
       string(0) ""
       ["post_status"]=>
       string(7) "publish"
       ["comment_status"]=>
       string(4) "open"
       ["ping_status"]=>
       string(4) "open"
       ["post_password"]=>
       string(0) ""
       ["post_name"]=>
       string(11) "hello-world"
       ["to_ping"]=>
       string(0) ""
       ["pinged"]=>
       string(0) ""
       ["post_modified"]=>
       string(19) "2022-09-13 14:48:41"
       ["post_modified_gmt"]=>
       string(19) "2022-09-13 14:48:41"
       ["post_content_filtered"]=>
       string(0) ""
       ["post_parent"]=>
       int(0)
       ["guid"]=>
       string(30) "http://two.wordpress.test/?p=1"
       ["menu_order"]=>
       int(0)
       ["post_type"]=>
       string(4) "post"
       ["post_mime_type"]=>
       string(0) ""
       ["comment_count"]=>
       string(1) "1"
       ["filter"]=>
       string(3) "raw"
     }
     ["found"]=>
     bool(true)
   }
   [";m-5D,iJF-
 Mw)[Tyqe0M^sxEU:_xgOC=N&d3Urn[z{d9FI0D0ExTtJ&Q/r}>0#wj:1673948700806564:wp_:category_relationships:1"]=>
   array(2) {
     ["value"]=>
     array(1) {
       [0]=>
       int(1)
     }
     ["found"]=>
     bool(true)
   }
   [";m-5D,iJF-
 Mw)[Tyqe0M^sxEU:_xgOC=N&d3Urn[z{d9FI0D0ExTtJ&Q/r}>0#wj:1673948700806564:wp_:post_tag_relationships:1"]=>
   array(2) {
     ["value"]=>
     array(0) {
     }
     ["found"]=>
     bool(true)
   }
   [";m-5D,iJF-
 Mw)[Tyqe0M^sxEU:_xgOC=N&d3Urn[z{d9FI0D0ExTtJ&Q/r}>0#wj:1673948700806564:wp_:post_format_relationships:1"]=>
   array(2) {
     ["value"]=>
     array(0) {
     }
     ["found"]=>
     bool(true)
   }
   [";m-5D,iJF-
 Mw)[Tyqe0M^sxEU:_xgOC=N&d3Urn[z{d9FI0D0ExTtJ&Q/r}>0#wj:1673948700806564:wp_:post_meta:1"]=>
   array(2) {
     ["value"]=>
     array(0) {
     }
     ["found"]=>
     bool(true)
   }
 }
 }}}

 The difference in the behaviour is what is increasing the memory
 consumption when the r55035 is in place (as it replaces the call to
 `_prime_post_caches` for `update_post_caches`).

 The example shown above follows the similar logic as if the code were
 executed in the `WP_Query` where the results of the `WP_Query` were
 cached. The posts are primed via `_prime_post_caches` in
 https://github.com/WordPress/wordpress-develop/blob/trunk/src/wp-includes
 /class-wp-query.php#L3137 and then all the caches are added via
 `update_post_caches` in https://github.com/WordPress/wordpress-
 develop/blob/trunk/src/wp-includes/class-wp-query.php#L3479 . Previously
 the `_prime_post_caches` was used (subject of the r55035 ).

 I'd like to point out that without the warm caches the OOM fatals I'm
 mentioning in my original comment would still happen, but the changeset
 makes them happen even with the caches being warm, and warming up the
 caches does not make the OOM to go away.

 IMHO, the current behaviour (with r55035  applied) is more correct, as it
 properly respect the `update_post_meta_cache` param of the `WP_Query`, but
 the memory impact can be significant in certain situations. So I'd like to
 make sure this aspect of the changeset is taken into consideration.

 Please, let me know if it makes the point I made cleaner.

-- 
Ticket URL: <https://core.trac.wordpress.org/ticket/57373#comment:15>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list