[wp-trac] [WordPress Trac] #35816: Add "after_get_posts" action to `WP_Query::get_posts()`
WordPress Trac
noreply at wordpress.org
Fri Feb 12 15:45:49 UTC 2016
#35816: Add "after_get_posts" action to `WP_Query::get_posts()`
---------------------------+-----------------------------
Reporter: stevegrunwell | Owner:
Type: defect (bug) | Status: new
Priority: normal | Milestone: Awaiting Review
Component: Query | Version: trunk
Severity: normal | Keywords:
Focuses: performance |
---------------------------+-----------------------------
When troubleshooting a long-running WP-CLI script on
[https://github.com/10up/ElasticPress ElasticPress], @lpawlik discovered
an issue within `WP_Query::get_posts()` that can have major implications
on memory consumption.
In a nutshell, when `update_post_meta_cache` and/or
`update_post_term_cache` aren't explicitly set to false (for instance, if
the query is called by way of `get_posts()`), then we end up hooking
callbacks like this:
{{{
if ( $q['update_post_term_cache'] ) {
add_filter( 'get_term_metadata', array( $this, 'lazyload_term_meta' ),
10, 2 );
}
}}}
On a normal web request, this isn't a huge deal, but this can become
catastrophic memory-wise for long running scripts: the fact that the
`lazyload_term_meta()` method is being hooked for each `WP_Query` instance
means that PHP's garbage collector can't clean up old query objects (since
they're still technically in-use).
Again, this often isn't an issue for any but the most intensive web
requests, as we're usually not iterating through tens of thousands of
posts and, when we do, the garbage collector automatically runs when the
script terminates. However, for teams doing large-scale migrations and
heavier data processing, it would be great to have a way to explicitly
unset callbacks unintentionally set on hooks like "get_term_metadata".
I propose adding an "after_get_posts" action, called right at the end of
`WP_Query::get_posts()` that acts as the sunset to `pre_get_posts`
sunrise. The `WP_Query` instance would be passed by reference, and teams
that '''do''' need to worry about garbage collection could use something
like this:
{{{
/**
* Remove WP_Query hooks on get_term_metadata, as they prevent PHP's
garbage collection from
* cleaning up old instances.
*
* @param WP_Query $query The WP_Query instance (passed by reference).
*/
function my_cli_script_unset_get_term_metadata( $query ) {
remove_filter( 'get_term_metadata', array( $query,
'lazyload_term_meta' ) );
}
add_action( 'after_get_posts', 'my_cli_script_unset_get_term_metadata' );
}}}
--
Ticket URL: <https://core.trac.wordpress.org/ticket/35816>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform
More information about the wp-trac
mailing list