mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Merge pull request #3934 from dhensby/pulls/cofig-lru-fix
Change the LRU cache to a simple in-memory model
This commit is contained in:
commit
93dca9aabd
@ -250,7 +250,7 @@ class Config {
|
|||||||
* leak through to other instances.
|
* leak through to other instances.
|
||||||
*/
|
*/
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
$this->cache = new Config_LRU();
|
$this->cache = new Config_MemCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __clone() {
|
public function __clone() {
|
||||||
@ -681,6 +681,7 @@ class Config {
|
|||||||
/**
|
/**
|
||||||
* @package framework
|
* @package framework
|
||||||
* @subpackage core
|
* @subpackage core
|
||||||
|
* @deprecated 3.2
|
||||||
*/
|
*/
|
||||||
class Config_LRU {
|
class Config_LRU {
|
||||||
const SIZE = 1000;
|
const SIZE = 1000;
|
||||||
@ -692,6 +693,7 @@ class Config_LRU {
|
|||||||
protected $c = 0;
|
protected $c = 0;
|
||||||
|
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
|
Deprecation::notice('3.2', 'Please use Config_MemCache instead', Deprecation::SCOPE_CLASS);
|
||||||
if (version_compare(PHP_VERSION, '5.3.7', '<')) {
|
if (version_compare(PHP_VERSION, '5.3.7', '<')) {
|
||||||
// SplFixedArray causes seg faults before PHP 5.3.7
|
// SplFixedArray causes seg faults before PHP 5.3.7
|
||||||
$this->cache = array();
|
$this->cache = array();
|
||||||
@ -787,6 +789,69 @@ class Config_LRU {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @package framework
|
||||||
|
* @subpackage core
|
||||||
|
*/
|
||||||
|
class Config_MemCache {
|
||||||
|
protected $cache;
|
||||||
|
|
||||||
|
protected $i = 0;
|
||||||
|
protected $c = 0;
|
||||||
|
protected $tags = array();
|
||||||
|
|
||||||
|
public function __construct() {
|
||||||
|
$this->cache = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function set($key, $val, $tags = array()) {
|
||||||
|
foreach($tags as $t) {
|
||||||
|
if(!isset($this->tags[$t])) {
|
||||||
|
$this->tags[$t] = array();
|
||||||
|
}
|
||||||
|
$this->tags[$t][$key] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->cache[$key] = array($val, $tags);
|
||||||
|
}
|
||||||
|
|
||||||
|
private $hit = 0;
|
||||||
|
private $miss = 0;
|
||||||
|
|
||||||
|
public function stats() {
|
||||||
|
return $this->miss ? ($this->hit / $this->miss) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get($key) {
|
||||||
|
if(isset($this->cache[$key])) {
|
||||||
|
++$this->hit;
|
||||||
|
return $this->cache[$key][0];
|
||||||
|
}
|
||||||
|
|
||||||
|
++$this->miss;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function clean($tag = null) {
|
||||||
|
if($tag) {
|
||||||
|
if(isset($this->tags[$tag])) {
|
||||||
|
foreach($this->tags[$tag] as $k => $dud) {
|
||||||
|
// Remove the key from everywhere else it is tagged
|
||||||
|
$ts = $this->cache[$k][1];
|
||||||
|
foreach($ts as $t) {
|
||||||
|
unset($this->tags[$t][$k]);
|
||||||
|
}
|
||||||
|
unset($this->cache[$k]);
|
||||||
|
}
|
||||||
|
unset($this->tags[$tag]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->cache = array();
|
||||||
|
$this->tags = array();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @package framework
|
* @package framework
|
||||||
* @subpackage core
|
* @subpackage core
|
||||||
|
@ -254,54 +254,92 @@ class ConfigTest extends SapphireTest {
|
|||||||
$this->markTestIncomplete();
|
$this->markTestIncomplete();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testLRUDiscarding() {
|
public function testCacheCleaning() {
|
||||||
$cache = new ConfigTest_Config_LRU();
|
$cache = new ConfigTest_Config_MemCache();
|
||||||
|
|
||||||
|
for ($i = 0; $i < 1000; $i++) $cache->set($i, $i);
|
||||||
|
$this->assertEquals(1000, count($cache->cache));
|
||||||
|
|
||||||
|
$cache->clean();
|
||||||
|
$this->assertEquals(0, count($cache->cache), 'Clean clears all items');
|
||||||
|
$this->assertFalse($cache->get(1), 'Clean clears all items');
|
||||||
|
|
||||||
|
$cache->set(1, 1, array('Foo'));
|
||||||
|
$this->assertEquals(1, count($cache->cache));
|
||||||
|
$this->assertEquals(1, count($cache->tags));
|
||||||
|
|
||||||
|
$cache->clean('Foo');
|
||||||
|
$this->assertEquals(0, count($cache->tags), 'Clean items with matching tag');
|
||||||
|
$this->assertFalse($cache->get(1), 'Clean items with matching tag');
|
||||||
|
|
||||||
|
$cache->set(1, 1, array('Foo', 'Bar'));
|
||||||
|
$this->assertEquals(2, count($cache->tags));
|
||||||
|
$this->assertEquals(1, count($cache->cache));
|
||||||
|
|
||||||
|
$cache->clean('Bar');
|
||||||
|
$this->assertEquals(1, count($cache->tags));
|
||||||
|
$this->assertEquals(0, count($cache->cache), 'Clean items with any single matching tag');
|
||||||
|
$this->assertFalse($cache->get(1), 'Clean items with any single matching tag');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testLRUDiscarding() {
|
||||||
|
$depSettings = Deprecation::dump_settings();
|
||||||
|
Deprecation::restore_settings(array(
|
||||||
|
'level' => false,
|
||||||
|
'version' => false,
|
||||||
|
'moduleVersions' => false,
|
||||||
|
));
|
||||||
|
$cache = new ConfigTest_Config_LRU();
|
||||||
for ($i = 0; $i < Config_LRU::SIZE*2; $i++) $cache->set($i, $i);
|
for ($i = 0; $i < Config_LRU::SIZE*2; $i++) $cache->set($i, $i);
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
Config_LRU::SIZE, count($cache->indexing),
|
Config_LRU::SIZE, count($cache->indexing),
|
||||||
'Homogenous usage gives exact discarding'
|
'Homogenous usage gives exact discarding'
|
||||||
);
|
);
|
||||||
|
|
||||||
$cache = new ConfigTest_Config_LRU();
|
$cache = new ConfigTest_Config_LRU();
|
||||||
|
|
||||||
for ($i = 0; $i < Config_LRU::SIZE; $i++) $cache->set($i, $i);
|
for ($i = 0; $i < Config_LRU::SIZE; $i++) $cache->set($i, $i);
|
||||||
for ($i = 0; $i < Config_LRU::SIZE; $i++) $cache->set(-1, -1);
|
for ($i = 0; $i < Config_LRU::SIZE; $i++) $cache->set(-1, -1);
|
||||||
$this->assertLessThan(
|
$this->assertLessThan(
|
||||||
Config_LRU::SIZE, count($cache->indexing),
|
Config_LRU::SIZE, count($cache->indexing),
|
||||||
'Heterogenous usage gives sufficient discarding'
|
'Heterogenous usage gives sufficient discarding'
|
||||||
);
|
);
|
||||||
|
Deprecation::restore_settings($depSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testLRUCleaning() {
|
public function testLRUCleaning() {
|
||||||
|
$depSettings = Deprecation::dump_settings();
|
||||||
|
Deprecation::restore_settings(array(
|
||||||
|
'level' => false,
|
||||||
|
'version' => false,
|
||||||
|
'moduleVersions' => false,
|
||||||
|
));
|
||||||
$cache = new ConfigTest_Config_LRU();
|
$cache = new ConfigTest_Config_LRU();
|
||||||
|
|
||||||
for ($i = 0; $i < Config_LRU::SIZE; $i++) $cache->set($i, $i);
|
for ($i = 0; $i < Config_LRU::SIZE; $i++) $cache->set($i, $i);
|
||||||
$this->assertEquals(Config_LRU::SIZE, count($cache->indexing));
|
$this->assertEquals(Config_LRU::SIZE, count($cache->indexing));
|
||||||
|
|
||||||
$cache->clean();
|
$cache->clean();
|
||||||
$this->assertEquals(0, count($cache->indexing), 'Clean clears all items');
|
$this->assertEquals(0, count($cache->indexing), 'Clean clears all items');
|
||||||
$this->assertFalse($cache->get(1), 'Clean clears all items');
|
$this->assertFalse($cache->get(1), 'Clean clears all items');
|
||||||
|
|
||||||
$cache->set(1, 1, array('Foo'));
|
$cache->set(1, 1, array('Foo'));
|
||||||
$this->assertEquals(1, count($cache->indexing));
|
$this->assertEquals(1, count($cache->indexing));
|
||||||
|
|
||||||
$cache->clean('Foo');
|
$cache->clean('Foo');
|
||||||
$this->assertEquals(0, count($cache->indexing), 'Clean items with matching tag');
|
$this->assertEquals(0, count($cache->indexing), 'Clean items with matching tag');
|
||||||
$this->assertFalse($cache->get(1), 'Clean items with matching tag');
|
$this->assertFalse($cache->get(1), 'Clean items with matching tag');
|
||||||
|
|
||||||
$cache->set(1, 1, array('Foo', 'Bar'));
|
$cache->set(1, 1, array('Foo', 'Bar'));
|
||||||
$this->assertEquals(1, count($cache->indexing));
|
$this->assertEquals(1, count($cache->indexing));
|
||||||
|
|
||||||
$cache->clean('Bar');
|
$cache->clean('Bar');
|
||||||
$this->assertEquals(0, count($cache->indexing), 'Clean items with any single matching tag');
|
$this->assertEquals(0, count($cache->indexing), 'Clean items with any single matching tag');
|
||||||
$this->assertFalse($cache->get(1), 'Clean items with any single matching tag');
|
$this->assertFalse($cache->get(1), 'Clean items with any single matching tag');
|
||||||
|
Deprecation::restore_settings($depSettings);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ConfigTest_Config_LRU extends Config_LRU implements TestOnly {
|
class ConfigTest_Config_LRU extends Config_LRU implements TestOnly {
|
||||||
|
|
||||||
public $cache;
|
public $cache;
|
||||||
public $indexing;
|
public $indexing;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ConfigTest_Config_MemCache extends Config_MemCache implements TestOnly {
|
||||||
|
|
||||||
|
public $cache;
|
||||||
|
public $tags;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user