diff --git a/lib/Alchemy/Phrasea/Core/Event/Subscriber/CacheStatisticsSubscriber.php b/lib/Alchemy/Phrasea/Core/Event/Subscriber/CacheStatisticsSubscriber.php
index ab39cc8dd5..c0f05b6def 100644
--- a/lib/Alchemy/Phrasea/Core/Event/Subscriber/CacheStatisticsSubscriber.php
+++ b/lib/Alchemy/Phrasea/Core/Event/Subscriber/CacheStatisticsSubscriber.php
@@ -66,6 +66,15 @@ class CacheStatisticsSubscriber implements EventSubscriberInterface
return [];
}
+ public function getTimeSpent()
+ {
+ if ($this->cache instanceof TraceableCache) {
+ return $this->cache->getTotalTime();
+ }
+
+ return 0;
+ }
+
public function getCacheType()
{
return $this->cacheType;
diff --git a/lib/Alchemy/Phrasea/Core/Profiler/CacheDataCollector.php b/lib/Alchemy/Phrasea/Core/Profiler/CacheDataCollector.php
index d0d6bdc6a8..893c6bceb6 100644
--- a/lib/Alchemy/Phrasea/Core/Profiler/CacheDataCollector.php
+++ b/lib/Alchemy/Phrasea/Core/Profiler/CacheDataCollector.php
@@ -30,6 +30,11 @@ class CacheDataCollector implements DataCollectorInterface
*/
private $summary;
+ /**
+ * @var int
+ */
+ private $timeSpent = 0;
+
/**
* @var array
*/
@@ -70,15 +75,17 @@ class CacheDataCollector implements DataCollectorInterface
$this->startProfile = new CacheProfile($this->statsListener->getInitialStats() ?: []);
$this->endProfile = new CacheProfile($this->statsListener->getCurrentStats() ?: []);
+ $this->timeSpent = $this->statsListener->getTimeSpent();
+ $this->calls = $this->statsListener->getCalls();
+ $this->callSummary = $this->statsListener->getCallSummary();
+
$this->summary = new CacheProfileSummary(
$this->statsListener->getCacheType(),
$this->statsListener->getCacheNamespace(),
$this->startProfile,
- $this->endProfile
+ $this->endProfile,
+ $this->callSummary
);
-
- $this->calls = $this->statsListener->getCalls();
- $this->callSummary = $this->statsListener->getCallSummary();
}
/**
@@ -97,6 +104,14 @@ class CacheDataCollector implements DataCollectorInterface
return $this->endProfile;
}
+ /**
+ * @return int
+ */
+ public function getTotalTime()
+ {
+ return $this->timeSpent;
+ }
+
public function getCalls()
{
return $this->calls;
diff --git a/lib/Alchemy/Phrasea/Core/Profiler/CacheProfileSummary.php b/lib/Alchemy/Phrasea/Core/Profiler/CacheProfileSummary.php
index 67bcc481e6..80ab9d864e 100644
--- a/lib/Alchemy/Phrasea/Core/Profiler/CacheProfileSummary.php
+++ b/lib/Alchemy/Phrasea/Core/Profiler/CacheProfileSummary.php
@@ -24,18 +24,30 @@ class CacheProfileSummary
*/
private $finalProfile;
+ /**
+ * @var array
+ */
+ private $callSummaryData;
+
/**
* @param string $cacheType
* @param string $namespace
* @param CacheProfile $initialProfile
* @param CacheProfile $finalProfile
+ * @param array $callSummaryData
*/
- public function __construct($cacheType, $namespace, CacheProfile $initialProfile, CacheProfile $finalProfile)
- {
- $this->cacheType = (string) $cacheType;
- $this->cacheNamespace = (string) $namespace;
+ public function __construct(
+ $cacheType,
+ $namespace,
+ CacheProfile $initialProfile,
+ CacheProfile $finalProfile,
+ array $callSummaryData
+ ) {
+ $this->cacheType = (string)$cacheType;
+ $this->cacheNamespace = (string)$namespace;
$this->initialProfile = $initialProfile;
$this->finalProfile = $finalProfile;
+ $this->callSummaryData = $callSummaryData;
}
/**
@@ -59,7 +71,11 @@ class CacheProfileSummary
*/
public function getHits()
{
- return (int) max(0, $this->finalProfile->getHits() - $this->initialProfile->getHits());
+ if (isset($this->callSummaryData['hits'])) {
+ return (int) $this->callSummaryData['hits'];
+ }
+
+ return (int)max(0, $this->finalProfile->getHits() - $this->initialProfile->getHits());
}
/**
@@ -67,7 +83,11 @@ class CacheProfileSummary
*/
public function getMisses()
{
- return (int) max(0, $this->finalProfile->getMisses() - $this->initialProfile->getMisses());
+ if (isset($this->callSummaryData['misses'])) {
+ return (int) $this->callSummaryData['misses'];
+ }
+
+ return (int)max(0, $this->finalProfile->getMisses() - $this->initialProfile->getMisses());
}
/**
@@ -75,6 +95,10 @@ class CacheProfileSummary
*/
public function getCalls()
{
+ if (isset($this->callSummaryData['calls'])) {
+ return (int) $this->callSummaryData['calls'];
+ }
+
return $this->getHits() + $this->getMisses();
}
@@ -86,7 +110,7 @@ class CacheProfileSummary
$calls = $this->getCalls();
if ($calls == 0) {
- return (float) 0;
+ return (float)0;
}
return $this->getHits() / $calls;
@@ -100,7 +124,7 @@ class CacheProfileSummary
$calls = $this->getCalls();
if ($calls == 0) {
- return (float) 0;
+ return (float)0;
}
return $this->getMisses() / $calls;
diff --git a/lib/Alchemy/Phrasea/Core/Profiler/TraceableCache.php b/lib/Alchemy/Phrasea/Core/Profiler/TraceableCache.php
index 3f336b8abf..cbdaf1b9c9 100644
--- a/lib/Alchemy/Phrasea/Core/Profiler/TraceableCache.php
+++ b/lib/Alchemy/Phrasea/Core/Profiler/TraceableCache.php
@@ -5,6 +5,7 @@ namespace Alchemy\Phrasea\Core\Profiler;
use Alchemy\Phrasea\Cache\Cache as PhraseaCache;
use Alchemy\Phrasea\Cache\Exception;
use Doctrine\Common\Cache\Cache;
+use Symfony\Component\Stopwatch\Stopwatch;
class TraceableCache implements Cache, PhraseaCache
{
@@ -32,12 +33,15 @@ class TraceableCache implements Cache, PhraseaCache
'calls_by_key' => [],
];
+ private $stopWatch;
+
/*s*
* @param PhraseaCache $cache
*/
- public function __construct(PhraseaCache $cache)
+ public function __construct(PhraseaCache $cache, Stopwatch $stopwatch = null)
{
$this->cache = $cache;
+ $this->stopWatch = $stopwatch ?: new Stopwatch();
}
private function collect($type, $id, $hit = true, $result = null)
@@ -90,6 +94,14 @@ class TraceableCache implements Cache, PhraseaCache
return $this->namespace;
}
+ /**
+ * @return int
+ */
+ public function getTotalTime()
+ {
+ return $this->stopWatch->getEvent('cache')->getDuration();
+ }
+
/**
* @return array
*/
@@ -116,7 +128,9 @@ class TraceableCache implements Cache, PhraseaCache
public function fetch($id)
{
try {
+ $this->stopWatch->start('cache');
$value = $this->cache->fetch($id);
+ $this->stopWatch->stop('cache');
}
catch (\Exception $ex) {
$value = false;
@@ -138,7 +152,11 @@ class TraceableCache implements Cache, PhraseaCache
{
$this->collect('contains', $id);
- return $this->cache->contains($id);
+ $this->stopWatch->start('cache');
+ $result = $this->cache->contains($id);
+ $this->stopWatch->stop('cache');
+
+ return $result;
}
/**
@@ -158,7 +176,11 @@ class TraceableCache implements Cache, PhraseaCache
{
$this->collect('save', $id);
- return $this->cache->save($id, $data, $lifeTime);
+ $this->stopWatch->start('cache');
+ $result = $this->cache->save($id, $data, $lifeTime);
+ $this->stopWatch->stop('cache');
+
+ return $result;
}
/**
@@ -173,7 +195,11 @@ class TraceableCache implements Cache, PhraseaCache
{
$this->collect('delete', $id);
- return $this->cache->delete($id);
+ $this->stopWatch->start('cache');
+ $result = $this->cache->delete($id);
+ $this->stopWatch->stop('cache');
+
+ return $result;
}
/**
@@ -202,7 +228,11 @@ class TraceableCache implements Cache, PhraseaCache
*/
public function getStats()
{
- return $this->cache->getStats();
+ $this->stopWatch->start('cache');
+ $result = $this->cache->getStats();
+ $this->stopWatch->stop('cache');
+
+ return $result;
}
/**
@@ -222,7 +252,9 @@ class TraceableCache implements Cache, PhraseaCache
public function flushAll()
{
$this->collect('flush-all', null);
+ $this->stopWatch->start('cache');
$this->cache->flushAll();
+ $this->stopWatch->stop('cache');
}
/**
diff --git a/templates-profiler/cache.html.twig b/templates-profiler/cache.html.twig
index 3bdce87625..45b2f7a264 100644
--- a/templates-profiler/cache.html.twig
+++ b/templates-profiler/cache.html.twig
@@ -13,7 +13,7 @@
{% endset %}
{% set icon %}
- {{ '%0.2f'|format(collector.summary.hitRatio * 100) }} % cache hit ratio
+ {{ '%0.2f'|format(collector.summary.hitRatio * 100) }} % in {{ collector.totalTime }} ms
{% endset %}
{% include '@WebProfiler/Profiler/toolbar_item.html.twig' with { 'link': profiler_url } %}
{% endblock %}
@@ -21,6 +21,10 @@
{% block menu %}
Cache
+
+ {{ collector.summary.hits }}
+ {{ '%0.0f'|format(collector.totalTime) }} ms
+
{% endblock %}