From 53b226d0e3d81c0cf45b2b39b506275a7a149ebe Mon Sep 17 00:00:00 2001 From: cash Date: Sat, 13 Apr 2013 14:28:01 -0400 Subject: adds LRU cache --- engine/classes/ElggLRUCache.php | 132 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 engine/classes/ElggLRUCache.php (limited to 'engine/classes/ElggLRUCache.php') diff --git a/engine/classes/ElggLRUCache.php b/engine/classes/ElggLRUCache.php new file mode 100644 index 000000000..add78ecb4 --- /dev/null +++ b/engine/classes/ElggLRUCache.php @@ -0,0 +1,132 @@ +maximumSize = $size; + } + + /** + * Get the value cached with this key + * + * @param int|string $key The key. Strings that are ints are cast to ints. + * @param mixed $default The value to be returned if key not found. (Optional) + * @return mixed + */ + public function get($key, $default = null) { + if (isset($this->data[$key])) { + $this->recordAccess($key); + return $this->data[$key]; + } else { + return $default; + } + } + + /** + * Put something in the cache + * + * @param int|string $key The key. Strings that are ints are cast to ints. + * @param mixed $value The value to cache + * @return void + */ + public function put($key, $value) { + if (isset($this->data[$key])) { + $this->data[$key] = $value; + $this->recordAccess($key); + } else { + $this->data[$key] = $value; + if ($this->size() > $this->maximumSize) { + // remove least recently used element (front of array) + reset($this->data); + unset($this->data[key($this->data)]); + } + } + } + + /** + * Get the number of elements in the cache + * + * @return int + */ + public function size() { + return count($this->data); + } + + /** + * Does the cache contain an element with this key + * + * @param int|string $key The key + * @return boolean + */ + public function containsKey($key) { + return isset($this->data[$key]); + } + + /** + * Remove the element with this key. + * + * @param int|string $key The key + * @return mixed Value or null if not set + */ + public function remove($key) { + if (isset($this->data[$key])) { + $value = $this->data[$key]; + unset($this->data[$key]); + return $value; + } else { + return null; + } + } + + /** + * Clear the cache + * + * @return void + */ + public function clear() { + $this->data = array(); + } + + /** + * Moves the element from current position to end of array + * + * @param int|string $key The key + * @return void + */ + protected function recordAccess($key) { + $value = $this->data[$key]; + unset($this->data[$key]); + $this->data[$key] = $value; + } +} -- cgit v1.2.3 From fc9a1e985b0b20c74a913f22ec9ea7e0c16848a7 Mon Sep 17 00:00:00 2001 From: cash Date: Sat, 13 Apr 2013 14:35:24 -0400 Subject: updated lru cache so easier to integrate --- engine/classes/ElggLRUCache.php | 55 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 3 deletions(-) (limited to 'engine/classes/ElggLRUCache.php') diff --git a/engine/classes/ElggLRUCache.php b/engine/classes/ElggLRUCache.php index add78ecb4..90e63bb61 100644 --- a/engine/classes/ElggLRUCache.php +++ b/engine/classes/ElggLRUCache.php @@ -13,7 +13,7 @@ * @package Elgg.Core * @subpackage Cache */ -class ElggLRUCache { +class ElggLRUCache implements ArrayAccess { /** @var int */ protected $maximumSize; @@ -54,13 +54,13 @@ class ElggLRUCache { } /** - * Put something in the cache + * Add something to the cache * * @param int|string $key The key. Strings that are ints are cast to ints. * @param mixed $value The value to cache * @return void */ - public function put($key, $value) { + public function set($key, $value) { if (isset($this->data[$key])) { $this->data[$key] = $value; $this->recordAccess($key); @@ -129,4 +129,53 @@ class ElggLRUCache { unset($this->data[$key]); $this->data[$key] = $value; } + + /** + * Assigns a value for the specified key + * + * @see ArrayAccess::offsetSet() + * + * @param int|string $key The key to assign the value to. + * @param mixed $value The value to set. + * @return void + */ + function offsetSet($key, $value) { + $this->set($key, $value); + } + + /** + * Get the value for specified key + * + * @see ArrayAccess::offsetGet() + * + * @param int|string $key The key to retrieve. + * @return mixed + */ + function offsetGet($key) { + return $this->get($key); + } + + /** + * Unsets a key. + * + * @see ArrayAccess::offsetUnset() + * + * @param int|string $key The key to unset. + * @return void + */ + function offsetUnset($key) { + $this->remove($key); + } + + /** + * Does key exist? + * + * @see ArrayAccess::offsetExists() + * + * @param int|string $key A key to check for. + * @return boolean + */ + function offsetExists($key) { + return $this->containsKey($key); + } } -- cgit v1.2.3 From 21c92cf39d719a913cd9e29474c04781e9cd72ef Mon Sep 17 00:00:00 2001 From: cash Date: Sat, 13 Apr 2013 15:05:40 -0400 Subject: Fixes #4978 integrates LRU cache for db query cache --- engine/classes/ElggLRUCache.php | 8 ++++---- engine/lib/database.php | 29 +++++++++++++++-------------- 2 files changed, 19 insertions(+), 18 deletions(-) (limited to 'engine/classes/ElggLRUCache.php') diff --git a/engine/classes/ElggLRUCache.php b/engine/classes/ElggLRUCache.php index 90e63bb61..f51af2ed7 100644 --- a/engine/classes/ElggLRUCache.php +++ b/engine/classes/ElggLRUCache.php @@ -139,7 +139,7 @@ class ElggLRUCache implements ArrayAccess { * @param mixed $value The value to set. * @return void */ - function offsetSet($key, $value) { + public function offsetSet($key, $value) { $this->set($key, $value); } @@ -151,7 +151,7 @@ class ElggLRUCache implements ArrayAccess { * @param int|string $key The key to retrieve. * @return mixed */ - function offsetGet($key) { + public function offsetGet($key) { return $this->get($key); } @@ -163,7 +163,7 @@ class ElggLRUCache implements ArrayAccess { * @param int|string $key The key to unset. * @return void */ - function offsetUnset($key) { + public function offsetUnset($key) { $this->remove($key); } @@ -175,7 +175,7 @@ class ElggLRUCache implements ArrayAccess { * @param int|string $key A key to check for. * @return boolean */ - function offsetExists($key) { + public function offsetExists($key) { return $this->containsKey($key); } } diff --git a/engine/lib/database.php b/engine/lib/database.php index b41eb4cda..3553d787d 100644 --- a/engine/lib/database.php +++ b/engine/lib/database.php @@ -12,18 +12,19 @@ /** * Query cache for all queries. * - * Each query and its results are stored in this array as: + * Each query and its results are stored in this cache as: * - * $DB_QUERY_CACHE[$query] => array(result1, result2, ... resultN) + * $DB_QUERY_CACHE[query hash] => array(result1, result2, ... resultN) * + * @see elgg_query_runner() for details on the hash. * - * @warning be array this var may be an array or ElggStaticVariableCache depending on when called :( + * @warning Elgg used to set this as an empty array to turn off the cache * - * @global ElggStaticVariableCache|array $DB_QUERY_CACHE + * @global ElggLRUCache|null $DB_QUERY_CACHE * @access private */ global $DB_QUERY_CACHE; -$DB_QUERY_CACHE = array(); +$DB_QUERY_CACHE = null; /** * Queries to be executed upon shutdown. @@ -127,9 +128,8 @@ function establish_db_link($dblinkname = "readwrite") { // Set up cache if global not initialized and query cache not turned off if ((!$DB_QUERY_CACHE) && (!$db_cache_off)) { - // @todo everywhere else this is assigned to array(), making it dangerous to call - // object methods on this. We should consider making this an plain array - $DB_QUERY_CACHE = new ElggStaticVariableCache('db_query_cache'); + // @todo if we keep this cache in 1.9, expose the size as a config parameter + $DB_QUERY_CACHE = new ElggLRUCache(200); } } @@ -404,11 +404,9 @@ function elgg_query_runner($query, $callback = null, $single = false) { // Is cached? if ($DB_QUERY_CACHE) { - $cached_query = $DB_QUERY_CACHE[$hash]; - - if ($cached_query !== FALSE) { + if (isset($DB_QUERY_CACHE[$hash])) { elgg_log("DB query $query results returned from cache (hash: $hash)", 'NOTICE'); - return $cached_query; + return $DB_QUERY_CACHE[$hash]; } } @@ -531,10 +529,13 @@ function delete_data($query) { */ function _elgg_invalidate_query_cache() { global $DB_QUERY_CACHE; - if ($DB_QUERY_CACHE) { - /* @var ElggStaticVariableCache $DB_QUERY_CACHE */ + if ($DB_QUERY_CACHE instanceof ElggLRUCache) { $DB_QUERY_CACHE->clear(); elgg_log("Query cache invalidated", 'NOTICE'); + } elseif ($DB_QUERY_CACHE) { + // In case someone sets the cache to an array and primes it with data + $DB_QUERY_CACHE = array(); + elgg_log("Query cache invalidated", 'NOTICE'); } } -- cgit v1.2.3