[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