MDL-39459 cache: mode included in stats output

The cache store mode is now included in the performance stats
printed at the bottom of the page.
It is represented as either [a] [s] or [r] and a title is used
to actually state the mode.
This commit is contained in:
Sam Hemelryk 2014-11-21 11:02:32 +13:00 committed by Sam Hemelryk
parent 4c27f52d91
commit 7fa57e0341
6 changed files with 129 additions and 61 deletions

View File

@ -346,9 +346,10 @@ class cache_helper {
/**
* Ensure that the stats array is ready to collect information for the given store and definition.
* @param string $store
* @param string $definition
* @param string $definition A string that identifies the definition.
* @param int $mode One of cache_store::MODE_*. Since 2.9.
*/
protected static function ensure_ready_for_stats($store, $definition) {
protected static function ensure_ready_for_stats($store, $definition, $mode = cache_store::MODE_APPLICATION) {
// This function is performance-sensitive, so exit as quickly as possible
// if we do not need to do anything.
if (isset(self::$stats[$definition][$store])) {
@ -356,14 +357,17 @@ class cache_helper {
}
if (!array_key_exists($definition, self::$stats)) {
self::$stats[$definition] = array(
$store => array(
'hits' => 0,
'misses' => 0,
'sets' => 0,
'mode' => $mode,
'stores' => array(
$store => array(
'hits' => 0,
'misses' => 0,
'sets' => 0,
)
)
);
} else if (!array_key_exists($store, self::$stats[$definition])) {
self::$stats[$definition][$store] = array(
self::$stats[$definition]['stores'][$store] = array(
'hits' => 0,
'misses' => 0,
'sets' => 0,
@ -371,43 +375,80 @@ class cache_helper {
}
}
/**
* Returns a string to describe the definition.
*
* This method supports the definition as a string due to legacy requirements.
* It is backwards compatible when a string is passed but is not accurate.
*
* @since 2.9
* @param cache_definition|string $definition
* @return string
*/
protected static function get_definition_stat_id_and_mode($definition) {
if (!($definition instanceof cache_definition)) {
// All core calls to this method have been updated, this is the legacy state.
// We'll use application as the default as that is the most common, really this is not accurate of course but
// at this point we can only guess and as it only affects calls to cache stat outside of core (of which there should
// be none) I think that is fine.
debugging('Please update you cache stat calls to pass the definition rather than just its ID.', DEBUG_DEVELOPER);
return array((string)$definition, cache_store::MODE_APPLICATION);
}
return array($definition->get_id(), $definition->get_mode());
}
/**
* Record a cache hit in the stats for the given store and definition.
*
* In Moodle 2.9 the $definition argument changed from accepting only a string to accepting a string or a
* cache_definition instance. It is preferable to pass a cache definition instance.
*
* @internal
* @param string $store
* @param string $definition
* @param cache_definition $store
* @param cache_definition $definition You used to be able to pass a string here, however that is deprecated please pass the
* actual cache_definition object now.
* @param int $hits The number of hits to record (by default 1)
*/
public static function record_cache_hit($store, $definition, $hits = 1) {
self::ensure_ready_for_stats($store, $definition);
self::$stats[$definition][$store]['hits'] += $hits;
list($definitionstr, $mode) = self::get_definition_stat_id_and_mode($definition);
self::ensure_ready_for_stats($store, $definitionstr, $mode);
self::$stats[$definitionstr]['stores'][$store]['hits'] += $hits;
}
/**
* Record a cache miss in the stats for the given store and definition.
*
* In Moodle 2.9 the $definition argument changed from accepting only a string to accepting a string or a
* cache_definition instance. It is preferable to pass a cache definition instance.
*
* @internal
* @param string $store
* @param string $definition
* @param cache_definition $definition You used to be able to pass a string here, however that is deprecated please pass the
* actual cache_definition object now.
* @param int $misses The number of misses to record (by default 1)
*/
public static function record_cache_miss($store, $definition, $misses = 1) {
self::ensure_ready_for_stats($store, $definition);
self::$stats[$definition][$store]['misses'] += $misses;
list($definitionstr, $mode) = self::get_definition_stat_id_and_mode($definition);
self::ensure_ready_for_stats($store, $definitionstr, $mode);
self::$stats[$definitionstr]['stores'][$store]['misses'] += $misses;
}
/**
* Record a cache set in the stats for the given store and definition.
*
* In Moodle 2.9 the $definition argument changed from accepting only a string to accepting a string or a
* cache_definition instance. It is preferable to pass a cache definition instance.
*
* @internal
* @param string $store
* @param string $definition
* @param cache_definition $definition You used to be able to pass a string here, however that is deprecated please pass the
* actual cache_definition object now.
* @param int $sets The number of sets to record (by default 1)
*/
public static function record_cache_set($store, $definition, $sets = 1) {
self::ensure_ready_for_stats($store, $definition);
self::$stats[$definition][$store]['sets'] += $sets;
list($definitionstr, $mode) = self::get_definition_stat_id_and_mode($definition);
self::ensure_ready_for_stats($store, $definitionstr, $mode);
self::$stats[$definitionstr]['stores'][$store]['sets'] += $sets;
}
/**

View File

@ -317,7 +317,7 @@ class cache implements cache_loader {
$setaftervalidation = false;
if ($result === false) {
if ($this->perfdebug) {
cache_helper::record_cache_miss($this->storetype, $this->definition->get_id());
cache_helper::record_cache_miss($this->storetype, $this->definition);
}
if ($this->loader !== false) {
// We must pass the original (unparsed) key to the next loader in the chain.
@ -329,7 +329,7 @@ class cache implements cache_loader {
}
$setaftervalidation = ($result !== false);
} else if ($this->perfdebug) {
cache_helper::record_cache_hit($this->storetype, $this->definition->get_id());
cache_helper::record_cache_hit($this->storetype, $this->definition);
}
// 5. Validate strictness.
if ($strictness === MUST_EXIST && $result === false) {
@ -473,8 +473,8 @@ class cache implements cache_loader {
$hits++;
}
}
cache_helper::record_cache_hit($this->storetype, $this->definition->get_id(), $hits);
cache_helper::record_cache_miss($this->storetype, $this->definition->get_id(), $misses);
cache_helper::record_cache_hit($this->storetype, $this->definition, $hits);
cache_helper::record_cache_miss($this->storetype, $this->definition, $misses);
}
// Return the result. Phew!
@ -500,7 +500,7 @@ class cache implements cache_loader {
*/
public function set($key, $data) {
if ($this->perfdebug) {
cache_helper::record_cache_set($this->storetype, $this->definition->get_id());
cache_helper::record_cache_set($this->storetype, $this->definition);
}
if ($this->loader !== false) {
// We have a loader available set it there as well.
@ -649,7 +649,7 @@ class cache implements cache_loader {
}
$successfullyset = $this->store->set_many($data);
if ($this->perfdebug && $successfullyset) {
cache_helper::record_cache_set($this->storetype, $this->definition->get_id(), $successfullyset);
cache_helper::record_cache_set($this->storetype, $this->definition, $successfullyset);
}
return $successfullyset;
}
@ -1039,7 +1039,7 @@ class cache implements cache_loader {
}
if ($result) {
if ($this->perfdebug) {
cache_helper::record_cache_hit('** static acceleration **', $this->definition->get_id());
cache_helper::record_cache_hit('** static acceleration **', $this->definition);
}
if ($this->staticaccelerationsize > 1 && $this->staticaccelerationcount > 1) {
// Check to see if this is the last item on the static acceleration keys array.
@ -1053,7 +1053,7 @@ class cache implements cache_loader {
return $result;
} else {
if ($this->perfdebug) {
cache_helper::record_cache_miss('** static acceleration **', $this->definition->get_id());
cache_helper::record_cache_miss('** static acceleration **', $this->definition);
}
return false;
}
@ -1779,7 +1779,7 @@ class cache_session extends cache {
// 4. Load if from the loader/datasource if we don't already have it.
if ($result === false) {
if ($this->perfdebug) {
cache_helper::record_cache_miss($this->storetype, $this->get_definition()->get_id());
cache_helper::record_cache_miss($this->storetype, $this->get_definition());
}
if ($this->get_loader() !== false) {
// We must pass the original (unparsed) key to the next loader in the chain.
@ -1794,7 +1794,7 @@ class cache_session extends cache {
$this->set($key, $result);
}
} else if ($this->perfdebug) {
cache_helper::record_cache_hit($this->storetype, $this->get_definition()->get_id());
cache_helper::record_cache_hit($this->storetype, $this->get_definition());
}
// 5. Validate strictness.
if ($strictness === MUST_EXIST && $result === false) {
@ -1838,7 +1838,7 @@ class cache_session extends cache {
$loader->set($key, $data);
}
if ($this->perfdebug) {
cache_helper::record_cache_set($this->storetype, $this->get_definition()->get_id());
cache_helper::record_cache_set($this->storetype, $this->get_definition());
}
if (is_object($data) && $data instanceof cacheable_object) {
$data = new cache_cached_object($data);
@ -1962,8 +1962,8 @@ class cache_session extends cache {
$hits++;
}
}
cache_helper::record_cache_hit($this->storetype, $this->get_definition()->get_id(), $hits);
cache_helper::record_cache_miss($this->storetype, $this->get_definition()->get_id(), $misses);
cache_helper::record_cache_hit($this->storetype, $this->get_definition(), $hits);
cache_helper::record_cache_miss($this->storetype, $this->get_definition(), $misses);
}
return $return;
@ -2040,7 +2040,7 @@ class cache_session extends cache {
}
$successfullyset = $this->get_store()->set_many($data);
if ($this->perfdebug && $successfullyset) {
cache_helper::record_cache_set($this->storetype, $definitionid, $successfullyset);
cache_helper::record_cache_set($this->storetype, $this->get_definition(), $successfullyset);
}
return $successfullyset;
}

1
cache/upgrade.txt vendored
View File

@ -12,6 +12,7 @@ Information provided here is intended especially for developers.
- cache::make Argument 4 (final arg) is now unused.
* cache_config_phpunittest has been renamed to cache_config_testing
* New method cache_store::ready_to_be_used_for_testing() that returns true|false if the store is suitable and ready for use as the primary store during unit and acceptance tests.
* cache_helper::get_stats structure we changed to include the cache mode.
=== 2.7 ===
* cache_store::is_ready is no longer abstract, calling cache_store::are_requirements_met by default.

View File

@ -9051,11 +9051,25 @@ function get_performance_info() {
$hits = 0;
$misses = 0;
$sets = 0;
foreach ($stats as $definition => $stores) {
$html .= '<span class="cache-definition-stats">';
$html .= '<span class="cache-definition-stats-heading">'.$definition.'</span>';
foreach ($stats as $definition => $details) {
switch ($details['mode']) {
case cache_store::MODE_APPLICATION:
$modeclass = 'application';
$mode = ' <span title="application cache">[a]</span>';
break;
case cache_store::MODE_SESSION:
$modeclass = 'session';
$mode = ' <span title="session cache">[s]</span>';
break;
case cache_store::MODE_REQUEST:
$modeclass = 'request';
$mode = ' <span title="request cache">[r]</span>';
break;
}
$html .= '<span class="cache-definition-stats cache-mode-'.$modeclass.'">';
$html .= '<span class="cache-definition-stats-heading">'.$definition.$mode.'</span>';
$text .= "$definition {";
foreach ($stores as $store => $data) {
foreach ($details['stores'] as $store => $data) {
$hits += $data['hits'];
$misses += $data['misses'];
$sets += $data['sets'];

View File

@ -45,33 +45,45 @@
margin-right: 10px;
margin-left: 10px;
}
.performanceinfo .cachesused {
/** Cache stats styles **/
#page-footer .performanceinfo .cachesused {
margin-top: 1em;
.cache-stats-heading,
.cache-total-stats {
font-weight: bold;
font-size: 110%;
margin-top: 0.3em;
}
.cache-definition-stats {
margin: .3em;
display: inline-block;
vertical-align: top;
background-color: @wellBackground;
.cache-definition-stats-heading span {
display: inline-block;
cursor: default;
}
.cache-store-stats {
padding: 0 1.3em;
&.nohits {
background-color: @errorBackground;
}
&.lowhits {
background-color: @warningBackground;
}
&.hihits {
background-color: @successBackground;
}
}
}
}
.performanceinfo .cachesused .cache-stats-heading,
.performanceinfo .cachesused .cache-total-stats {
font-weight: bold;
font-size: 110%;
margin-top: 0.3em;
}
#page-footer .performanceinfo .cachesused .cache-definition-stats {
margin: .3em;
display: inline-block;
vertical-align: top;
background-color: @wellBackground;
}
.cache-store-stats {
padding: 0 1.3em;
}
.cache-store-stats.nohits {
background-color: @errorBackground;
}
.cache-store-stats.lowhits {
background-color: @warningBackground;
}
.cache-store-stats.hihits {
background-color: @successBackground;
}
#page-footer,
#page-footer .validators,
#page-footer .purgecaches,

File diff suppressed because one or more lines are too long