MDL-40538 caching: Use isset for performance

isset is much faster than array_key_exists. For caches we need to
ensure as much performance as possible. To all null to continue to
be stored and provide correct results, non ttl also now saves in
$this->store[$key][0].  As isset($this->store[$key]) will return
true in all cases.

time() as found in cache::now() can be slow on some platforms and
we shouldn't bother checking it unless needed. It also stops non-ttl
caches paying the ttl price.

Unit tests were adjusted to ensure null is still handled correctly
when we are only using isset.
This commit is contained in:
Russell Smith 2013-07-09 10:10:17 +10:00
parent f8e6e5bc30
commit ae21341523
3 changed files with 82 additions and 61 deletions

View file

@ -218,11 +218,10 @@ class cachestore_session extends session_data_store implements cache_is_key_awar
* @return mixed The data that was associated with the key, or false if the key did not exist. * @return mixed The data that was associated with the key, or false if the key did not exist.
*/ */
public function get($key) { public function get($key) {
$maxtime = cache::now() - $this->ttl; if (isset($this->store[$key])) {
if (array_key_exists($key, $this->store)) {
if ($this->ttl == 0) { if ($this->ttl == 0) {
return $this->store[$key]; return $this->store[$key][0];
} else if ($this->store[$key][1] >= $maxtime) { } else if ($this->store[$key][1] >= (cache::now() - $this->ttl)) {
return $this->store[$key][0]; return $this->store[$key][0];
} }
} }
@ -240,12 +239,15 @@ class cachestore_session extends session_data_store implements cache_is_key_awar
*/ */
public function get_many($keys) { public function get_many($keys) {
$return = array(); $return = array();
$maxtime = cache::now() - $this->ttl; if ($this->ttl != 0) {
$maxtime = cache::now() - $this->ttl;
}
foreach ($keys as $key) { foreach ($keys as $key) {
$return[$key] = false; $return[$key] = false;
if (array_key_exists($key, $this->store)) { if (isset($this->store[$key])) {
if ($this->ttl == 0) { if ($this->ttl == 0) {
$return[$key] = $this->store[$key]; $return[$key] = $this->store[$key][0];
} else if ($this->store[$key][1] >= $maxtime) { } else if ($this->store[$key][1] >= $maxtime) {
$return[$key] = $this->store[$key][0]; $return[$key] = $this->store[$key][0];
} }
@ -263,7 +265,7 @@ class cachestore_session extends session_data_store implements cache_is_key_awar
*/ */
public function set($key, $data) { public function set($key, $data) {
if ($this->ttl == 0) { if ($this->ttl == 0) {
$this->store[$key] = $data; $this->store[$key][0] = $data;
} else { } else {
$this->store[$key] = array($data, cache::now()); $this->store[$key] = array($data, cache::now());
} }
@ -294,11 +296,10 @@ class cachestore_session extends session_data_store implements cache_is_key_awar
* @return bool * @return bool
*/ */
public function has($key) { public function has($key) {
$maxtime = cache::now() - $this->ttl; if (isset($this->store[$key])) {
if (array_key_exists($key, $this->store)) {
if ($this->ttl == 0) { if ($this->ttl == 0) {
return true; return true;
} else if ($this->store[$key][1] >= $maxtime) { } else if ($this->store[$key][1] >= (cache::now() - $this->ttl)) {
return true; return true;
} }
} }
@ -312,9 +313,12 @@ class cachestore_session extends session_data_store implements cache_is_key_awar
* @return bool * @return bool
*/ */
public function has_all(array $keys) { public function has_all(array $keys) {
$maxtime = cache::now() - $this->ttl; if ($this->ttl != 0) {
$maxtime = cache::now() - $this->ttl;
}
foreach ($keys as $key) { foreach ($keys as $key) {
if (!array_key_exists($key, $this->store)) { if (!isset($this->store[$key])) {
return false; return false;
} }
if ($this->ttl != 0 && $this->store[$key][1] < $maxtime) { if ($this->ttl != 0 && $this->store[$key][1] < $maxtime) {
@ -331,9 +335,12 @@ class cachestore_session extends session_data_store implements cache_is_key_awar
* @return bool * @return bool
*/ */
public function has_any(array $keys) { public function has_any(array $keys) {
$maxtime = cache::now() - $this->ttl; if ($this->ttl != 0) {
$maxtime = cache::now() - $this->ttl;
}
foreach ($keys as $key) { foreach ($keys as $key) {
if (array_key_exists($key, $this->store) && ($this->ttl == 0 || $this->store[$key][1] >= $maxtime)) { if (isset($this->store[$key]) && ($this->ttl == 0 || $this->store[$key][1] >= $maxtime)) {
return true; return true;
} }
} }

View file

@ -213,11 +213,10 @@ class cachestore_static extends static_data_store implements cache_is_key_aware
* @return mixed The data that was associated with the key, or false if the key did not exist. * @return mixed The data that was associated with the key, or false if the key did not exist.
*/ */
public function get($key) { public function get($key) {
$maxtime = cache::now() - $this->ttl; if (isset($this->store[$key])) {
if (array_key_exists($key, $this->store)) {
if ($this->ttl == 0) { if ($this->ttl == 0) {
return $this->store[$key]; return $this->store[$key][0];
} else if ($this->store[$key][1] >= $maxtime) { } else if ($this->store[$key][1] >= (cache::now() - $this->ttl)) {
return $this->store[$key][0]; return $this->store[$key][0];
} }
} }
@ -235,12 +234,15 @@ class cachestore_static extends static_data_store implements cache_is_key_aware
*/ */
public function get_many($keys) { public function get_many($keys) {
$return = array(); $return = array();
$maxtime = cache::now() - $this->ttl; if ($this->ttl != 0) {
$maxtime = cache::now() - $this->ttl;
}
foreach ($keys as $key) { foreach ($keys as $key) {
$return[$key] = false; $return[$key] = false;
if (array_key_exists($key, $this->store)) { if (isset($this->store[$key])) {
if ($this->ttl == 0) { if ($this->ttl == 0) {
$return[$key] = $this->store[$key]; $return[$key] = $this->store[$key][0];
} else if ($this->store[$key][1] >= $maxtime) { } else if ($this->store[$key][1] >= $maxtime) {
$return[$key] = $this->store[$key][0]; $return[$key] = $this->store[$key][0];
} }
@ -258,7 +260,7 @@ class cachestore_static extends static_data_store implements cache_is_key_aware
*/ */
public function set($key, $data) { public function set($key, $data) {
if ($this->ttl == 0) { if ($this->ttl == 0) {
$this->store[$key] = $data; $this->store[$key][0] = $data;
} else { } else {
$this->store[$key] = array($data, cache::now()); $this->store[$key] = array($data, cache::now());
} }
@ -289,11 +291,10 @@ class cachestore_static extends static_data_store implements cache_is_key_aware
* @return bool * @return bool
*/ */
public function has($key) { public function has($key) {
$maxtime = cache::now() - $this->ttl; if (isset($this->store[$key])) {
if (array_key_exists($key, $this->store)) {
if ($this->ttl == 0) { if ($this->ttl == 0) {
return true; return true;
} else if ($this->store[$key][1] >= $maxtime) { } else if ($this->store[$key][1] >= (cache::now() - $this->ttl)) {
return true; return true;
} }
} }
@ -307,9 +308,12 @@ class cachestore_static extends static_data_store implements cache_is_key_aware
* @return bool * @return bool
*/ */
public function has_all(array $keys) { public function has_all(array $keys) {
$maxtime = cache::now() - $this->ttl; if ($this->ttl != 0) {
$maxtime = cache::now() - $this->ttl;
}
foreach ($keys as $key) { foreach ($keys as $key) {
if (!array_key_exists($key, $this->store)) { if (!isset($this->store[$key])) {
return false; return false;
} }
if ($this->ttl != 0 && $this->store[$key][1] < $maxtime) { if ($this->ttl != 0 && $this->store[$key][1] < $maxtime) {
@ -326,9 +330,12 @@ class cachestore_static extends static_data_store implements cache_is_key_aware
* @return bool * @return bool
*/ */
public function has_any(array $keys) { public function has_any(array $keys) {
$maxtime = cache::now() - $this->ttl; if ($this->ttl != 0) {
$maxtime = cache::now() - $this->ttl;
}
foreach ($keys as $key) { foreach ($keys as $key) {
if (array_key_exists($key, $this->store) && ($this->ttl == 0 || $this->store[$key][1] >= $maxtime)) { if (isset($this->store[$key]) && ($this->ttl == 0 || $this->store[$key][1] >= $maxtime)) {
return true; return true;
} }
} }

View file

@ -192,41 +192,43 @@ class cache_phpunit_tests extends advanced_testcase {
*/ */
protected function run_on_cache(cache_loader $cache) { protected function run_on_cache(cache_loader $cache) {
$key = 'testkey'; $key = 'testkey';
$datascalar = 'test data'; $datascalars = array('test data', null);
$dataarray = array('test' => 'data', 'part' => 'two'); $dataarray = array('test' => 'data', 'part' => 'two');
$dataobject = (object)$dataarray; $dataobject = (object)$dataarray;
$this->assertTrue($cache->purge()); foreach ($datascalars as $datascalar) {
$this->assertTrue($cache->purge());
// Check all read methods. // Check all read methods.
$this->assertFalse($cache->get($key)); $this->assertFalse($cache->get($key));
$this->assertFalse($cache->has($key)); $this->assertFalse($cache->has($key));
$result = $cache->get_many(array($key)); $result = $cache->get_many(array($key));
$this->assertCount(1, $result); $this->assertCount(1, $result);
$this->assertFalse(reset($result)); $this->assertFalse(reset($result));
$this->assertFalse($cache->has_any(array($key))); $this->assertFalse($cache->has_any(array($key)));
$this->assertFalse($cache->has_all(array($key))); $this->assertFalse($cache->has_all(array($key)));
// Set the data. // Set the data.
$this->assertTrue($cache->set($key, $datascalar)); $this->assertTrue($cache->set($key, $datascalar));
// Setting it more than once should be permitted. // Setting it more than once should be permitted.
$this->assertTrue($cache->set($key, $datascalar)); $this->assertTrue($cache->set($key, $datascalar));
// Recheck the read methods. // Recheck the read methods.
$this->assertEquals($datascalar, $cache->get($key)); $this->assertEquals($datascalar, $cache->get($key));
$this->assertTrue($cache->has($key)); $this->assertTrue($cache->has($key));
$result = $cache->get_many(array($key)); $result = $cache->get_many(array($key));
$this->assertCount(1, $result); $this->assertCount(1, $result);
$this->assertEquals($datascalar, reset($result)); $this->assertEquals($datascalar, reset($result));
$this->assertTrue($cache->has_any(array($key))); $this->assertTrue($cache->has_any(array($key)));
$this->assertTrue($cache->has_all(array($key))); $this->assertTrue($cache->has_all(array($key)));
// Delete it. // Delete it.
$this->assertTrue($cache->delete($key)); $this->assertTrue($cache->delete($key));
// Check its gone. // Check its gone.
$this->assertFalse($cache->get($key)); $this->assertFalse($cache->get($key));
$this->assertFalse($cache->has($key)); $this->assertFalse($cache->has($key));
}
// Test arrays. // Test arrays.
$this->assertTrue($cache->set($key, $dataarray)); $this->assertTrue($cache->set($key, $dataarray));
@ -261,11 +263,13 @@ class cache_phpunit_tests extends advanced_testcase {
} }
// Test set many. // Test set many.
$cache->set_many(array('key1' => 'data1', 'key2' => 'data2')); $cache->set_many(array('key1' => 'data1', 'key2' => 'data2', 'key3' => null));
$this->assertEquals('data1', $cache->get('key1')); $this->assertEquals('data1', $cache->get('key1'));
$this->assertEquals('data2', $cache->get('key2')); $this->assertEquals('data2', $cache->get('key2'));
$this->assertEquals(null, $cache->get('key3'));
$this->assertTrue($cache->delete('key1')); $this->assertTrue($cache->delete('key1'));
$this->assertTrue($cache->delete('key2')); $this->assertTrue($cache->delete('key2'));
$this->assertTrue($cache->delete('key3'));
$cache->set_many(array( $cache->set_many(array(
'key1' => array(1, 2, 3), 'key1' => array(1, 2, 3),
@ -282,14 +286,17 @@ class cache_phpunit_tests extends advanced_testcase {
// Test delete many. // Test delete many.
$this->assertTrue($cache->set('key1', 'data1')); $this->assertTrue($cache->set('key1', 'data1'));
$this->assertTrue($cache->set('key2', 'data2')); $this->assertTrue($cache->set('key2', 'data2'));
$this->assertTrue($cache->set('key3', null));
$this->assertEquals('data1', $cache->get('key1')); $this->assertEquals('data1', $cache->get('key1'));
$this->assertEquals('data2', $cache->get('key2')); $this->assertEquals('data2', $cache->get('key2'));
$this->assertEquals(null, $cache->get('key3'));
$this->assertEquals(2, $cache->delete_many(array('key1', 'key2'))); $this->assertEquals(3, $cache->delete_many(array('key1', 'key2', 'key3')));
$this->assertFalse($cache->get('key1')); $this->assertFalse($cache->get('key1'));
$this->assertFalse($cache->get('key2')); $this->assertFalse($cache->get('key2'));
$this->assertFalse($cache->get('key3'));
// Quick reference test. // Quick reference test.
$obj = new stdClass; $obj = new stdClass;