From ddbaea8d8e1ba56f83c5f9d92e9819bce9929f6d Mon Sep 17 00:00:00 2001 From: Suso Bravo-Alvarez Date: Mon, 24 Aug 2020 23:15:30 +0200 Subject: [PATCH] Support for wp_cache_get_multiple() from WP 5.5 - Moved most code from wp_cache_get_multi() to the new method - Using true memcached multiget instead of single gets in a loop - Kept wp_cache_get_multi() as a wrapper of the new method. The return value is slightly different, as it's not a map of the full memcache keys, but keys are just ':' --- object-cache.php | 125 ++++++++++++++++++++++++------------ tests/test-object-cache.php | 20 +++--- 2 files changed, 93 insertions(+), 52 deletions(-) diff --git a/object-cache.php b/object-cache.php index cdf1e5a..d669f5a 100644 --- a/object-cache.php +++ b/object-cache.php @@ -60,9 +60,15 @@ function wp_cache_get( $key, $group = '', $force = false, &$found = null ) { /** * Retrieve multiple cache entries - * - * @param array $groups Array of arrays, of groups and keys to retrieve - * @return mixed + */ +function wp_cache_get_multiple( $keys, $group = '', $force = false ) { + global $wp_object_cache; + + return $wp_object_cache->get_multiple( $keys, $group, $force ); +} + +/** + * Legacy method signature for wp_cache_get_multiple() */ function wp_cache_get_multi( $groups ) { global $wp_object_cache; @@ -354,61 +360,69 @@ function get( $id, $group = 'default', $force = false, &$found = null ) { return $value; } - function get_multi( $groups ) { - /* - format: $get['group-name'] = array( 'key1', 'key2' ); - */ + function get_multiple( $ids, $group = 'default', $force = false ) { + $mc =& $this->get_mc( $group ); + + $no_mc = in_array( $group, $this->no_mc_groups ); + + $uncached_keys = array(); + $return = array(); $return_cache = array( 'value' => false, 'found' => false, ); - foreach ( $groups as $group => $ids ) { - $mc =& $this->get_mc( $group ); - $keys = array(); - $this->timer_start(); + foreach ( $ids as $id ) { + $key = $this->key( $id, $group ); - foreach ( $ids as $id ) { - $key = $this->key( $id, $group ); - $keys[] = $key; - - if ( isset( $this->cache[ $key ] ) ) { - if ( is_object( $this->cache[ $key ][ 'value'] ) ) { - $return[ $key ] = clone $this->cache[ $key ][ 'value']; - $return_cache[ $key ] = [ - 'value' => clone $this->cache[ $key ][ 'value'], - 'found' => $this->cache[ $key ][ 'found'], - ]; - } else { - $return[ $key ] = $this->cache[ $key ][ 'value']; - $return_cache[ $key ] = [ - 'value' => $this->cache[ $key ][ 'value' ], - 'found' => $this->cache[ $key ][ 'found' ], - ]; - } - - continue; - } else if ( in_array( $group, $this->no_mc_groups ) ) { - $return[ $key ] = false; + if ( isset( $this->cache[ $key ] ) && ( ! $force || $no_mc ) ) { + if ( is_object( $this->cache[ $key ][ 'value' ] ) ) { + $return[ $id ] = clone $this->cache[ $key ][ 'value' ]; $return_cache[ $key ] = [ - 'value' => false, - 'found' => false, + 'value' => clone $this->cache[ $key ][ 'value' ], + 'found' => $this->cache[ $key ][ 'found' ], ]; - - continue; } else { - $fresh_get = $mc->get( $key ); - $return[ $key ] = $fresh_get; + $return[ $id ] = $this->cache[ $key ][ 'value' ]; $return_cache[ $key ] = [ - 'value' => $fresh_get, - 'found' => false !== $fresh_get, + 'value' => $this->cache[ $key ][ 'value' ], + 'found' => $this->cache[ $key ][ 'found' ], ]; } + + continue; + } else if ( $no_mc ) { + $return[ $id ] = false; + $return_cache[ $key ] = [ + 'value' => false, + 'found' => false, + ]; + + continue; + } else { + $uncached_keys[ $id ] = $key; } + } + + if ( $uncached_keys ) { + $this->timer_start(); + + $uncached_keys_list = array_values( $uncached_keys ); + $values = $mc->get( $uncached_keys_list ); $elapsed = $this->timer_stop(); - $this->group_ops_stats( 'get_multi', $keys, $group, null, $elapsed ); + $this->group_ops_stats( 'get_multiple', $uncached_keys_list, $group, null, $elapsed ); + + foreach ( $uncached_keys as $id => $key ) { + $value = isset( $values[$key] ) ? $values[$key] : false; + + $return[ $id ] = $value; + $return_cache[ $key ] = [ + 'value' => $value, + 'found' => false !== $value, + ]; + } } $this->cache = array_merge( $this->cache, $return_cache ); @@ -416,6 +430,33 @@ function get_multi( $groups ) { return $return; } + /** + * Legacy implementation for get_multiple + * + * Kept here for backwards compatibility + */ + function get_multi( $groups ) { + /* + format: $get['group-name'] = array( 'key1', 'key2' ); + */ + $return = array(); + + foreach ( $groups as $group => $ids ) { + $this->timer_start(); + $result = $this->get_multiple( $ids, $group ); + $elapsed = $this->timer_stop(); + + foreach ( $result as $id => $value ) { + $id_with_group = $group . ':' . $id; + $return[ $id_with_group ] = $value; + } + + $this->group_ops_stats( 'get_multi', $ids, $group, null, $elapsed ); + } + + return $return; + } + function flush_prefix( $group ) { if ( 'WP_Object_Cache' === $group || 'WP_Object_Cache_global' === $group ) { // Never flush the flush numbers. diff --git a/tests/test-object-cache.php b/tests/test-object-cache.php index 4d38af9..21dc022 100644 --- a/tests/test-object-cache.php +++ b/tests/test-object-cache.php @@ -509,8 +509,8 @@ public function test_get_multi_returns_array_of_values_from_memcache(): void { ); $expected = [ - $this->object_cache->key( 'foo', 'default') => 'data', - $this->object_cache->key( 'foo', 'another-group') => 'data', + 'default:foo' => 'data', + 'another-group:foo' => 'data', ]; $this->assertEquals( $expected, $values ); @@ -581,9 +581,9 @@ public function test_get_multi_returns_data_from_local_cache(): void { ); $expected = [ - $this->object_cache->key( 'foo', 'default') => 'data-updated', - $this->object_cache->key( 'foo', 'another-group') => 'data', - $this->object_cache->key( 'foo', 'and-another-group') => 'data', + 'default:foo' => 'data-updated', + 'another-group:foo' => 'data', + 'and-another-group:foo' => 'data', ]; $this->assertEquals( $expected, $values ); @@ -618,9 +618,9 @@ public function test_get_multi_returns_data_not_from_local_cache(): void { ); $expected = [ - $this->object_cache->key( 'foo', 'default') => 'data', - $this->object_cache->key( 'foo', 'another-group') => 'data', - $this->object_cache->key( 'foo', 'and-another-group') => 'data', + 'default:foo' => 'data', + 'another-group:foo' => 'data', + 'and-another-group:foo' => 'data', ]; $this->assertEquals( $expected, $values ); @@ -633,7 +633,7 @@ public function test_get_multi_only_uses_local_cache_when_using_non_persistent_g $this->object_cache->add( 'foo', 'data', $group ); $values = $this->object_cache->get_multi( [ $group => [ 'foo' ] ] ); - $expected = [ $this->object_cache->key( 'foo', $group ) => 'data' ]; + $expected = [ $group . ':foo' => 'data' ]; $this->assertEquals( $expected, $values ); $expected_cache = [ @@ -654,7 +654,7 @@ public function test_get_multi_returns_false_if_no_local_cache_when_using_non_pe unset( $this->object_cache->cache[ $key ] ); $values = $this->object_cache->get_multi( [ $group => [ 'foo' ] ] ); - $expected = [ $this->object_cache->key( 'foo', $group ) => false ]; + $expected = [ $group . ':foo' => false ]; $this->assertEquals( $expected, $values ); $this->assertFalse( $this->object_cache->cache[ $key ][ 'value' ] );