Make WordPress Core


Ignore:
Timestamp:
02/17/2016 10:57:33 PM (11 years ago)
Author:
boonebgorges
Message:

More performance improvements to metadata lazyloading.

Comment and term meta lazyloading for WP_Query loops, introduced in 4.4,
depended on filter callback methods belonging to WP_Query objects. This meant
storing WP_Query objects in the $wp_filter global (via add_filter()),
requiring that PHP retain the objects in memory, even when the local variables
would typically be expunged during normal garbage collection. In cases where a
large number of WP_Query objects were instantiated on a single pageload,
and/or where the contents of the WP_Query objects were quite large, serious
performance issues could result.

We skirt this problem by moving metadata lazyloading out of WP_Query. The
new WP_Metadata_Lazyloader class acts as a lazyload queue. Query instances
register items whose metadata should be lazyloaded - such as post terms, or
comments - and a WP_Metadata_Lazyloader method will intercept comment and
term meta requests to perform the cache priming. Since WP_Metadata_Lazyloader
instances are far smaller than WP_Query (containing only object IDs), and
clean up after themselves far better than the previous WP_Query methods (bp
only running their callbacks a single time for a given set of queued objects),
the resource use is decreased dramatically.

See [36525] for an earlier step in this direction.

Props lpawlik, stevegrunwell, boonebgorges.
Fixes #35816.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tests/phpunit/tests/term/meta.php

    r35585 r36566  
    135135                                $num_queries = $wpdb->num_queries;
    136136                                $this->assertSame( 'bar', get_term_meta( $terms[0], 'foo', true ) );
    137                                 $this->assertSame( $num_queries + 1, $wpdb->num_queries );
     137                                $num_queries++;
     138                                $this->assertSame( $num_queries, $wpdb->num_queries );
    138139
    139140                                // Second and third requests should be in cache.
    140141                                $this->assertSame( 'bar', get_term_meta( $terms[1], 'foo', true ) );
    141142                                $this->assertSame( 'bar', get_term_meta( $terms[2], 'foo', true ) );
    142                                 $this->assertSame( $num_queries + 1, $wpdb->num_queries );
     143                                $this->assertSame( $num_queries, $wpdb->num_queries );
    143144
    144145                                // Querying a term not primed should result in a hit.
     146                                $num_queries++;
    145147                                $this->assertSame( 'bar', get_term_meta( $orphan_term, 'foo', true ) );
    146                                 $this->assertSame( $num_queries + 2, $wpdb->num_queries );
     148                                $this->assertSame( $num_queries, $wpdb->num_queries );
    147149                        }
    148150                }
    149151        }
    150152
    151         /**
    152          * @ticket 34073
    153          */
    154         public function test_term_meta_should_be_lazy_loaded_only_for_the_queries_in_which_the_term_has_posts() {
    155                 global $wpdb;
    156 
    157                 $posts = self::factory()->post->create_many( 3, array( 'post_status' => 'publish' ) );
    158                 register_taxonomy( 'wptests_tax', 'post' );
    159                 $terms = self::factory()->term->create_many( 6, array( 'taxonomy' => 'wptests_tax' ) );
    160 
    161                 wp_set_object_terms( $posts[0], array( $terms[0], $terms[1] ), 'wptests_tax' );
    162                 wp_set_object_terms( $posts[1], array( $terms[2], $terms[3] ), 'wptests_tax' );
    163                 wp_set_object_terms( $posts[2], array( $terms[0], $terms[4], $terms[5] ), 'wptests_tax' );
    164 
    165                 foreach ( $terms as $t ) {
    166                         add_term_meta( $t, 'foo', 'bar' );
    167                 }
    168 
    169                 $q0 = new WP_Query( array( 'p' => $posts[0], 'cache_results' => true ) );
    170                 $q1 = new WP_Query( array( 'p' => $posts[1], 'cache_results' => true ) );
    171                 $q2 = new WP_Query( array( 'p' => $posts[2], 'cache_results' => true ) );
    172 
    173                 /*
    174                  * $terms[0] belongs to both $posts[0] and $posts[2], so `get_term_meta( $terms[0] )` should prime
    175                  * the cache for term matched by $q0 and $q2.
    176                  */
    177 
    178                 // First request will hit the database.
    179                 $num_queries = $wpdb->num_queries;
    180 
    181                 // Prime caches.
    182                 $this->assertSame( 'bar', get_term_meta( $terms[0], 'foo', true ) );
    183 
    184                 // Two queries: one for $q0 and one for $q2.
    185                 $num_queries += 2;
    186                 $this->assertSame( $num_queries, $wpdb->num_queries );
    187 
    188                 // Next requests should be in cache.
    189                 $this->assertSame( 'bar', get_term_meta( $terms[1], 'foo', true ) );
    190                 $this->assertSame( 'bar', get_term_meta( $terms[4], 'foo', true ) );
    191                 $this->assertSame( 'bar', get_term_meta( $terms[5], 'foo', true ) );
    192                 $this->assertSame( $num_queries, $wpdb->num_queries );
    193 
    194                 // Querying for $terms[2] will prime $terms[3] as well.
    195                 $this->assertSame( 'bar', get_term_meta( $terms[2], 'foo', true ) );
    196                 $num_queries++;
    197                 $this->assertSame( $num_queries, $wpdb->num_queries );
    198 
    199                 $this->assertSame( 'bar', get_term_meta( $terms[3], 'foo', true ) );
    200                 $this->assertSame( $num_queries, $wpdb->num_queries );
    201         }
    202 
    203         public function test_adding_term_meta_should_bust_get_terms_cache() {
     153        public function test_updating_term_meta_should_bust_get_terms_cache() {
    204154                $terms = self::factory()->term->create_many( 2, array( 'taxonomy' => 'wptests_tax' ) );
    205155
    206156                add_term_meta( $terms[0], 'foo', 'bar' );
     157                add_term_meta( $terms[1], 'foo', 'baz' );
    207158
    208159                // Prime cache.
    … …  
    220171                $this->assertEqualSets( array( $terms[0] ), $found );
    221172
    222                 add_term_meta( $terms[1], 'foo', 'bar' );
     173                update_term_meta( $terms[1], 'foo', 'bar' );
    223174
    224175                $found = get_terms( 'wptests_tax', array(
    … …  
    236187        }
    237188
    238         public function test_updating_term_meta_should_bust_get_terms_cache() {
     189        public function test_deleting_term_meta_should_bust_get_terms_cache() {
    239190                $terms = self::factory()->term->create_many( 2, array( 'taxonomy' => 'wptests_tax' ) );
    240191
    241192                add_term_meta( $terms[0], 'foo', 'bar' );
    242                 add_term_meta( $terms[1], 'foo', 'baz' );
     193                add_term_meta( $terms[1], 'foo', 'bar' );
    243194
    244195                // Prime cache.
    … …  
    254205                ) );
    255206
    256                 $this->assertEqualSets( array( $terms[0] ), $found );
    257 
    258                 update_term_meta( $terms[1], 'foo', 'bar' );
     207                $this->assertEqualSets( array( $terms[0], $terms[1] ), $found );
     208
     209                delete_term_meta( $terms[1], 'foo', 'bar' );
    259210
    260211                $found = get_terms( 'wptests_tax', array(
    … …  
    269220                ) );
    270221
    271                 $this->assertEqualSets( array( $terms[0], $terms[1] ), $found );
    272         }
    273 
    274         public function test_deleting_term_meta_should_bust_get_terms_cache() {
    275                 $terms = self::factory()->term->create_many( 2, array( 'taxonomy' => 'wptests_tax' ) );
    276 
    277                 add_term_meta( $terms[0], 'foo', 'bar' );
    278                 add_term_meta( $terms[1], 'foo', 'bar' );
    279 
    280                 // Prime cache.
    281                 $found = get_terms( 'wptests_tax', array(
    282                         'hide_empty' => false,
    283                         'fields' => 'ids',
    284                         'meta_query' => array(
    285                                 array(
    286                                         'key' => 'foo',
    287                                         'value' => 'bar',
    288                                 ),
    289                         ),
    290                 ) );
    291 
    292                 $this->assertEqualSets( array( $terms[0], $terms[1] ), $found );
    293 
    294                 delete_term_meta( $terms[1], 'foo', 'bar' );
    295 
    296                 $found = get_terms( 'wptests_tax', array(
    297                         'hide_empty' => false,
    298                         'fields' => 'ids',
    299                         'meta_query' => array(
    300                                 array(
    301                                         'key' => 'foo',
    302                                         'value' => 'bar',
    303                                 ),
    304                         ),
    305                 ) );
    306 
    307222                $this->assertEqualSets( array( $terms[0] ), $found );
    308223        }
Note: See TracChangeset for help on using the changeset viewer.