[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