# HG changeset patch # User Arthur Lutz # Date 1488388069 -3600 # Node ID 39c9e548f0ceb1dd4945f77fa46195abc2d30d7b # Parent 2c83063b28e3240a4a75bfcd29f039ae09997491 [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 diff -r 2c83063b28e3 -r 39c9e548f0ce cubicweb/rqlrewrite.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() diff -r 2c83063b28e3 -r 39c9e548f0ce cubicweb/schema.py --- 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 ###########################################