On 11/28/07, Jonas Borgström <[EMAIL PROTECTED]> wrote:
> While porting the t.e.o theme to Trac trunk I noticed that the /roadmap
> is very slow, and it takes at least 1.5-2 seconds to render that page.
I was wondering if the permission system would have an impact, given how
much work it has to do.
> Almost all of that time is apparently spent by the permission system
> making sure the user isn't shown any ticket he/she isn't supposed to
> see:
>
> (roadmap.py:267)
> def apply_ticket_permissions(env, req, tickets):
> """Apply permissions to a set of milestone tickets as returned by
> get_tickets_for_milestone()."""
> return [t for t in tickets
> if 'TICKET_VIEW' in req.perm('ticket', t['id'])]
>
> If I'm reading perm.py correctly PermissionCache only caches repeated
> permission checks on a specific resource and action and not repeated
> checks on different resources in the same realm. This means that the
> apply_ticket_permission function will generate hundreds if not thousands
> of cache misses for larger Trac installations.
Correct. All permission checks are handed off to IPermissionPolicy
implementations, so it's impossible (currently) for the permission
system to know whether more aggressive caching is acceptable.
> What's even worse is that each and every cache miss results in a call to
> DefaultPermissionStore.get_user_permissions() which in turn executes a
> "SELECT username,action FROM permission". So almost all of the 1.5-2
> seconds are spent on repeatingly querying the database for the same
> information.
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.
>
> I don't know perm.py well enough right now to come with a good
> suggestion for how to fix this. But imho we need to find a way to
> improve the cache before 0.11 is released.
Try the patch out and let me know if it's much better.
--~--~---------~--~----~------------~-------~--~----~
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 6213)
+++ 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,11 +255,30 @@
implements(IPermissionPolicy)
+ # Number of seconds a cached user permission set is valid for.
+ CACHE_EXPIRY = 5
+
+ 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, permissions = self.permission_cache.get(username, (0, None))
+
+ # Cache hit?
+ if permissions is not None and now - timestamp < self.CACHE_EXPIRY:
+ return action in permissions
+
+ # No, pull permissions from database.
+ permissions = PermissionSystem(self.env). \
+ get_user_permissions(username)
+
+ self.permission_cache[username] = (now, permissions)
+ return action in permissions
+
class PermissionSystem(Component):