Alec Thomas wrote:
> On 11/28/07, Alec Thomas <[EMAIL PROTECTED]> wrote:
>   
>> On 11/28/07, Alec Thomas <[EMAIL PROTECTED]> wrote:
>>     
>>> This is the area that we can improve. Try the attached patch, it caches
>>> the results of get_user_permissions() for up to 5 seconds, which should
>>> massively reduce the number of hits on the database.
>>>       
>> Slightly cleaner patch attached.
>>     
>
> Testing with an old sqlite copy of the Trac database, I see the
> following results:
>
> Before the patch:
>
>   Permission checks on 2702 tickets took 1.29666638374 seconds
>
> After the patch:
>
>   Permission checks on 2702 tickets took 0.19308590889 seconds
>   

Well, that would do for the default permission policy. There should be 
at least some additional cleanup done at a larger interval to clear the 
whole cache, so that it doesn't explode over time if the server stays 
alive for long periods of time.

New version of the patch attached.

-- Christian


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Trac 
Development" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/trac-dev?hl=en
-~----------~----~----~----~------~----~------~--~---

Index: trac/perm.py
===================================================================
--- trac/perm.py	(revision 6242)
+++ trac/perm.py	(working copy)
@@ -18,6 +18,7 @@
 
 """Management of permissions."""
 
+from time import time
 from trac.config import ExtensionOption, OrderedExtensionsOption
 from trac.core import *
 from trac.resource import Resource, get_resource_name
@@ -254,13 +255,36 @@
 
     implements(IPermissionPolicy)
 
+    CACHE_EXPIRY = 60 # Number of seconds before clearing the whole cache
+    USER_CACHE_EXPIRY = 5 # Number of seconds before reloading user permissions 
+
+    def __init__(self):
+        self.permission_cache = {}
+
     # IPermissionPolicy methods
 
     def check_permission(self, action, username, resource, perm):
-        return PermissionSystem(self.env). \
-               get_user_permissions(username).get(action, None)
+        now = time()
+        timestamp = self.permission_cache.get(None, 0)
 
+        # Prevent an ever growing cache
+        if now - timestamp > self.CACHE_EXPIRY:
+            self.log.debug("Clearing the in-memory permission cache")
+            self.permission_cache.clear()
+            self.permission_cache[None] = now
 
+        # Cache hit?
+        timestamp, permissions = self.permission_cache.get(username, (0, None))
+        if now - timestamp > self.USER_CACHE_EXPIRY:
+            self.log.debug("Fetching permissions for %s from DB." % username)
+            permissions = PermissionSystem(self.env). \
+                          get_user_permissions(username)
+            self.permission_cache[username] = (now, permissions)
+
+        return action in permissions
+
+
+
 class PermissionSystem(Component):
     """Sub-system that manages user permissions."""
 

Reply via email to