Improve `WP_Query` lazyloading logic, for better performance.

Lazyloading for comment meta and term meta, introduced into `WP_Query` in
4.4, used flags - `updated_term_meta_cache` and `updated_comment_meta_cache` -
in an attempt to prevent cache priming from happening more than once per query
object. This technique was mostly effective, but not entirely efficient, since
the flag didn't prevent the `lazyload_*_meta` callbacks from running. The
obvious solution - removing the filter callback after it'd be run once - was
dismissed for 4.4 because of concerns that `remove_filter()` could disable
lazyloading too generally in the context of nested queries, due to the way
`_wp_filter_build_unique_id()` doesn't always build sufficiently unique IDs for
similar objects. However, further testing shows that this concern is only valid
in a very small subset of cases, while the cost of keeping the query objects in
memory, via the `$wp_filter` global, is quite significant. As such, this
changeset removes the flags in favor of the `remove_filter()` technique.

See #35454, #35816.

git-svn-id: https://develop.svn.wordpress.org/trunk@36524 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Boone Gorges 2016-02-13 03:04:05 +00:00
parent 9a108e99b5
commit d03ae82c32
1 changed files with 4 additions and 38 deletions

View File

@ -1303,24 +1303,6 @@ class WP_Query {
*/
public $thumbnails_cached = false;
/**
* Whether the term meta cache for matched posts has been primed.
*
* @since 4.4.0
* @access protected
* @var bool
*/
public $updated_term_meta_cache = false;
/**
* Whether the comment meta cache for matched posts has been primed.
*
* @since 4.4.0
* @access protected
* @var bool
*/
public $updated_comment_meta_cache = false;
/**
* Cached list of search stopwords.
*
@ -4874,14 +4856,6 @@ class WP_Query {
* another value if filtered by a plugin.
*/
public function lazyload_term_meta( $check, $term_id ) {
/*
* We only do this once per `WP_Query` instance.
* Can't use `remove_filter()` because of non-unique object hashes.
*/
if ( $this->updated_term_meta_cache ) {
return $check;
}
// We can only lazyload if the entire post object is present.
$posts = array();
foreach ( $this->posts as $post ) {
@ -4915,13 +4889,13 @@ class WP_Query {
*/
if ( isset( $term_ids[ $term_id ] ) ) {
update_termmeta_cache( array_keys( $term_ids ) );
$this->updated_term_meta_cache = true;
remove_filter( 'get_term_metadata', array( $this, 'lazyload_term_meta' ), 10, 2 );
}
}
// If no terms were found, there's no need to run this again.
if ( empty( $term_ids ) ) {
$this->updated_term_meta_cache = true;
remove_filter( 'get_term_metadata', array( $this, 'lazyload_term_meta' ), 10, 2 );
}
return $check;
@ -4940,14 +4914,6 @@ class WP_Query {
* @return mixed The original value of `$check`, to not affect 'get_comment_metadata'.
*/
public function lazyload_comment_meta( $check, $comment_id ) {
/*
* We only do this once per `WP_Query` instance.
* Can't use `remove_filter()` because of non-unique object hashes.
*/
if ( $this->updated_comment_meta_cache ) {
return $check;
}
// Don't use `wp_list_pluck()` to avoid by-reference manipulation.
$comment_ids = array();
if ( is_array( $this->comments ) ) {
@ -4963,9 +4929,9 @@ class WP_Query {
*/
if ( in_array( $comment_id, $comment_ids ) ) {
update_meta_cache( 'comment', $comment_ids );
$this->updated_comment_meta_cache = true;
remove_filter( 'get_comment_metadata', array( $this, 'lazyload_comment_meta' ), 10, 2 );
} elseif ( empty( $comment_ids ) ) {
$this->updated_comment_meta_cache = true;
remove_filter( 'get_comment_metadata', array( $this, 'lazyload_comment_meta' ), 10, 2 );
}
return $check;