Skip to content
This repository

Fix for CacheProvider serious performance issue #125

Merged
merged 3 commits into from about 2 years ago

6 participants

Przemek Sobstel Florin Patan Christophe Coevoet Benjamin Eberlei Guilherme Blanco florin-innobyte
Przemek Sobstel

Prior implementation for CacheProvider was seriously flawed from performance point of view as each fetch() call results in 2 additional cache storage calls due to $this->getNamespaceId(), which always checks for $namespaceCacheKey (and fetches it if exists, which will be the case for 2nd and next calls).

It is big overhead (3 calls instead just one for each fetch), and actually can be easily solved by memoizing namespace version value.

and others added some commits
Przemek Sobstel CacheProvider: memoize namespace version value.
Prior implementation for CacheProvider was seriously flawed
from performance point of view as each fetch() call results
in 2 additional cache storage calls due to $this->getNamespaceId(),
which always checks for $namespaceCacheKey (and fetches it if
exists, which will be the case for 2nd and next calls).
7bad040
florin-innobyte CacheProvider: avoid double call to fetch $namespaceVersion. 6d05190
lib/Doctrine/Common/Cache/CacheProvider.php
((17 lines not shown))
  151
+    {
  152
+        return sprintf(self::DOCTRINE_NAMESPACE_CACHEKEY, $this->namespace);
  153
+    }
  154
+
  155
+    /**
  156
+     * Namespace version
  157
+     *
  158
+     * @return string $namespaceVersion
  159
+     */
  160
+    private function getNamespaceVersion()
  161
+    {
  162
+        if (NULL === $this->namespaceVersion)
  163
+        {
  164
+            $namespaceCacheKey = $this->getNamespaceCacheKey();
  165
+            $namespaceVersion = $this->doFetch($namespaceCacheKey);
  166
+            if (false === $namespaceVersion) {
4
Benjamin Eberlei Owner
beberlei added a note

can you guarantee this for all cache drivers? or is false == the better condition here? Since its definately not 1 its a sufficient check.

Florin Patan
dlsniper added a note

Since @sobstel did the change on my recommendation I'd like to jump in on this one.

As mentioned on #122, "if the documentation here, https://github.com/doctrine/common/blob/master/lib/Doctrine/Common/Cache/CacheProvider.php#L144 , is right, then fetch will return FALSE in case the value is not found so I don't see a point in doing a trip to the caching server, ask if it has the value in it's cache, if it has fetch it, if not then" we should change the function documentation as it's wrong.

@beberlei what's your input on this?

Florin Patan
dlsniper added a note

I've also created some tests in #127 which should help with that but I couldn't test all the cache drivers. Memcache(d), APC, Array pass this condition, Zend should too since it's based on APC and I'm clueless about the rest.

Przemek Sobstel
sobstel added a note

"== condition" will also work as we're expecting integer here. We could even do ($namespaceVersion < 1) condition. But as doFetch($id) is supposed to return false, it should be ok as well. And if it's not case for some cache driver, then it should be fixed there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
lib/Doctrine/Common/Cache/CacheProvider.php
@@ -117,10 +122,11 @@ public function flushAll()
117 122
      */
118 123
     public function deleteAll()
119 124
     {
120  
-        $namespaceCacheKey = sprintf(self::DOCTRINE_NAMESPACE_CACHEKEY, $this->namespace);
121  
-        $namespaceVersion  = ($this->doContains($namespaceCacheKey)) ? $this->doFetch($namespaceCacheKey) : 1;
  125
+        $namespaceCacheKey = $this->getNamespaceCacheKey();
  126
+        $namespaceVersion  = $this->getNamespaceVersion() + 1;
  127
+        $this->namespaceVersion = $namespaceVersion;
1
Guilherme Blanco Owner

Add a line space before this line.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
lib/Doctrine/Common/Cache/CacheProvider.php
((13 lines not shown))
  147
+     *
  148
+     * @return string $namespaceCacheKey
  149
+     */
  150
+    private function getNamespaceCacheKey()
  151
+    {
  152
+        return sprintf(self::DOCTRINE_NAMESPACE_CACHEKEY, $this->namespace);
  153
+    }
  154
+
  155
+    /**
  156
+     * Namespace version
  157
+     *
  158
+     * @return string $namespaceVersion
  159
+     */
  160
+    private function getNamespaceVersion()
  161
+    {
  162
+        if (NULL === $this->namespaceVersion)
2
Guilherme Blanco Owner

Use "null" (lowercased) here

Christophe Coevoet Collaborator
stof added a note

and the curly brace should be on the same line than the if

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Guilherme Blanco guilhermeblanco commented on the diff
lib/Doctrine/Common/Cache/CacheProvider.php
((7 lines not shown))
136 141
 
137 142
         return sprintf('%s[%s][%s]', $this->namespace, $id, $namespaceVersion);
138 143
     }
139 144
 
140 145
     /**
  146
+     * Namespace cache key
  147
+     *
  148
+     * @return string $namespaceCacheKey
  149
+     */
  150
+    private function getNamespaceCacheKey()
  151
+    {
  152
+        return sprintf(self::DOCTRINE_NAMESPACE_CACHEKEY, $this->namespace);
  153
+    }
  154
+
  155
+    /**
  156
+     * Namespace version
  157
+     *
  158
+     * @return string $namespaceVersion
  159
+     */
  160
+    private function getNamespaceVersion()
1
Guilherme Blanco Owner

Ok, this whole code needs to be refactored.
It breaks the rule #1 of Object Calisthenics: "Only one level of indentation per method".
You can rewrite this one using early returns

private function getNamespaceVersion()
{
    if (null !== $this->namespaceVersion) {
        return $this->namespaceVersion;
    }

    $namespaceCacheKey = $this->getNamespaceCacheKey();
    $namespaceVersion  = $this->doFetch($namespaceCacheKey);

    if (false === $namespaceVersion) {
        $namespaceVersion = 1;

        $this->doSave($namespaceCacheKey, $namespaceVersion);
    }

    $this->namespaceVersion = $namespaceVersion;

    return $this->namespaceVersion;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
lib/Doctrine/Common/Cache/CacheProvider.php
@@ -40,6 +40,11 @@
40 40
     private $namespace = '';
41 41
 
42 42
     /**
  43
+     * @var string The namespace version
  44
+     */
  45
+    private $namespaceVersion = NULL;
1
Christophe Coevoet Collaborator
stof added a note

remove the = null. It is useless as it is already the default in PHP when omitting it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Florin Patan

Hi,

What's needed in order for this to be merged?

Thanks.

Christophe Coevoet
Collaborator
stof commented
Guilherme Blanco guilhermeblanco merged commit 4f78640 into from
Guilherme Blanco guilhermeblanco closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 3 unique commits by 2 authors.

Mar 28, 2012
Przemek Sobstel CacheProvider: memoize namespace version value.
Prior implementation for CacheProvider was seriously flawed
from performance point of view as each fetch() call results
in 2 additional cache storage calls due to $this->getNamespaceId(),
which always checks for $namespaceCacheKey (and fetches it if
exists, which will be the case for 2nd and next calls).
7bad040
Mar 29, 2012
florin-innobyte CacheProvider: avoid double call to fetch $namespaceVersion. 6d05190
Mar 31, 2012
Przemek Sobstel CacheProvider: adhere to Doctrine2 coding standards. 729a088
This page is out of date. Refresh to see the latest.
51  lib/Doctrine/Common/Cache/CacheProvider.php
@@ -40,6 +40,11 @@
40 40
     private $namespace = '';
41 41
 
42 42
     /**
  43
+     * @var string The namespace version
  44
+     */
  45
+    private $namespaceVersion;
  46
+
  47
+    /**
43 48
      * Set the namespace to prefix all cache ids with.
44 49
      *
45 50
      * @param string $namespace
@@ -117,10 +122,12 @@ public function flushAll()
117 122
      */
118 123
     public function deleteAll()
119 124
     {
120  
-        $namespaceCacheKey = sprintf(self::DOCTRINE_NAMESPACE_CACHEKEY, $this->namespace);
121  
-        $namespaceVersion  = ($this->doContains($namespaceCacheKey)) ? $this->doFetch($namespaceCacheKey) : 1;
  125
+        $namespaceCacheKey = $this->getNamespaceCacheKey();
  126
+        $namespaceVersion  = $this->getNamespaceVersion() + 1;
122 127
 
123  
-        return $this->doSave($namespaceCacheKey, $namespaceVersion + 1);
  128
+        $this->namespaceVersion = $namespaceVersion;
  129
+
  130
+        return $this->doSave($namespaceCacheKey, $namespaceVersion);
124 131
     }
125 132
 
126 133
     /**
@@ -131,13 +138,47 @@ public function deleteAll()
131 138
      */
132 139
     private function getNamespacedId($id)
133 140
     {
134  
-        $namespaceCacheKey = sprintf(self::DOCTRINE_NAMESPACE_CACHEKEY, $this->namespace);
135  
-        $namespaceVersion  = ($this->doContains($namespaceCacheKey)) ? $this->doFetch($namespaceCacheKey) : 1;
  141
+        $namespaceVersion  = $this->getNamespaceVersion();
136 142
 
137 143
         return sprintf('%s[%s][%s]', $this->namespace, $id, $namespaceVersion);
138 144
     }
139 145
 
140 146
     /**
  147
+     * Namespace cache key
  148
+     *
  149
+     * @return string $namespaceCacheKey
  150
+     */
  151
+    private function getNamespaceCacheKey()
  152
+    {
  153
+        return sprintf(self::DOCTRINE_NAMESPACE_CACHEKEY, $this->namespace);
  154
+    }
  155
+
  156
+    /**
  157
+     * Namespace version
  158
+     *
  159
+     * @return string $namespaceVersion
  160
+     */
  161
+    private function getNamespaceVersion()
  162
+    {
  163
+        if (null !== $this->namespaceVersion) {
  164
+            return $this->namespaceVersion;
  165
+        }
  166
+
  167
+        $namespaceCacheKey = $this->getNamespaceCacheKey();
  168
+        $namespaceVersion = $this->doFetch($namespaceCacheKey);
  169
+
  170
+        if (false === $namespaceVersion) {
  171
+            $namespaceVersion = 1;
  172
+
  173
+            $this->doSave($namespaceCacheKey, $namespaceVersion);
  174
+        }
  175
+
  176
+        $this->namespaceVersion = $namespaceVersion;
  177
+
  178
+        return $this->namespaceVersion;
  179
+    }
  180
+
  181
+    /**
141 182
      * Fetches an entry from the cache.
142 183
      *
143 184
      * @param string $id cache id The id of the cache entry to fetch.
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.