[rqlrewrite/schema] Avoid parsing computed relations for each query 3.25
authorArthur Lutz <arthur.lutz@logilab.fr>
Wed, 01 Mar 2017 18:07:49 +0100
branch3.25
changeset 12086 39c9e548f0ce
parent 12084 2c83063b28e3
child 12087 9f668acfa6c3
[rqlrewrite/schema] Avoid parsing computed relations for each query The RQLRelationRewriter is instanciated for each RQL query, it should avoid parsing computed relations formula by using a cache, which seems rightly located on the instance's schema. This brings a *huge* performance boost to some pages on application with a few computed relations (x4 observed on a client app). Kudos to Adrien, David and Sylvain. Closes #17059828
cubicweb/rqlrewrite.py
cubicweb/schema.py
--- a/cubicweb/rqlrewrite.py	Wed Mar 22 13:58:28 2017 +0100
+++ b/cubicweb/rqlrewrite.py	Wed Mar 01 18:07:49 2017 +0100
@@ -905,22 +905,18 @@
 
     This class *isn't thread safe*.
     """
-    def __init__(self, session):
-        super(RQLRelationRewriter, self).__init__(session)
-        self.rules = {}
-        for rschema in self.schema.iter_computed_relations():
-            self.rules[rschema.type] = RRQLExpression(rschema.rule)
 
     def rewrite(self, union, kwargs=None):
         self.kwargs = kwargs
         self.removing_ambiguity = False
         self.existingvars = None
         self.pending_keys = None
+        rules = self.schema.rules_rqlexpr_mapping
         for relation in union.iget_nodes(n.Relation):
-            if relation.r_type in self.rules:
+            if relation.r_type in rules:
                 self.select = relation.stmt
                 self.solutions = solutions = self.select.solutions[:]
-                self.current_expr = self.rules[relation.r_type]
+                self.current_expr = rules[relation.r_type]
                 self._insert_scope = relation.scope
                 self.rewritten = {}
                 lhs, rhs = relation.get_variable_parts()
--- a/cubicweb/schema.py	Wed Mar 22 13:58:28 2017 +0100
+++ b/cubicweb/schema.py	Wed Mar 01 18:07:49 2017 +0100
@@ -1008,6 +1008,16 @@
 
     etype_name_re = r'[A-Z][A-Za-z0-9]*[a-z]+[A-Za-z0-9]*$'
 
+    @cachedproperty
+    def rules_rqlexpr_mapping(self):
+        """Return a dictionary mapping rtype to RRQLExpression for computed
+        relations.
+        """
+        rules = {}
+        for rschema in self.iter_computed_relations():
+            rules[rschema.type] = RRQLExpression(rschema.rule)
+        return rules
+
     def add_entity_type(self, edef):
         edef.name = str(edef.name)
         edef.name = bw_normalize_etype(edef.name)
@@ -1148,6 +1158,8 @@
         super(CubicWebSchema, self).rebuild_infered_relations()
         self.finalize_computed_attributes()
         self.finalize_computed_relations()
+        # remove @cachedproperty cache
+        self.__dict__.pop('rules_rqlexpr_mapping', None)
 
 
 # additional cw specific constraints ###########################################