ASP-based solver: optimize key to intermediate dicts (#39471)

Computing str(spec) is faster than computing hash(spec), and
since all the abstract specs we deal with come from user configuration
they cannot cover DAG structures that are not captured by str() but
are captured by hash()
This commit is contained in:
Massimiliano Culpo 2023-08-17 14:11:49 +02:00 committed by GitHub
parent 82685a68d9
commit a022e45866
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -267,12 +267,14 @@ def _id(thing):
@llnl.util.lang.key_ordering
class AspFunction(AspObject):
__slots__ = ["name", "args"]
def __init__(self, name, args=None):
self.name = name
self.args = () if args is None else tuple(args)
def _cmp_key(self):
return (self.name, self.args)
return self.name, self.args
def __call__(self, *args):
"""Return a new instance of this function with added arguments.
@ -731,7 +733,9 @@ def fact(self, head):
"""
symbol = head.symbol() if hasattr(head, "symbol") else head
self.out.write("%s.\n" % str(symbol))
# This is commented out to avoid evaluating str(symbol) when we have no stream
if not isinstance(self.out, llnl.util.lang.Devnull):
self.out.write(f"{str(symbol)}.\n")
atom = self.backend.add_atom(symbol)
@ -1363,26 +1367,29 @@ def condition(self, required_spec, imposed_spec=None, name=None, msg=None, node=
self.gen.fact(fn.condition_reason(condition_id, msg))
cache = self._trigger_cache[named_cond.name]
if named_cond not in cache:
named_cond_key = str(named_cond)
if named_cond_key not in cache:
trigger_id = next(self._trigger_id_counter)
requirements = self.spec_clauses(named_cond, body=True, required_from=name)
cache[named_cond] = (trigger_id, requirements)
trigger_id, requirements = cache[named_cond]
cache[named_cond_key] = (trigger_id, requirements)
trigger_id, requirements = cache[named_cond_key]
self.gen.fact(fn.pkg_fact(named_cond.name, fn.condition_trigger(condition_id, trigger_id)))
if not imposed_spec:
return condition_id
cache = self._effect_cache[named_cond.name]
if imposed_spec not in cache:
imposed_spec_key = str(imposed_spec)
if imposed_spec_key not in cache:
effect_id = next(self._effect_id_counter)
requirements = self.spec_clauses(imposed_spec, body=False, required_from=name)
if not node:
requirements = list(
filter(lambda x: x.args[0] not in ("node", "virtual_node"), requirements)
)
cache[imposed_spec] = (effect_id, requirements)
effect_id, requirements = cache[imposed_spec]
cache[imposed_spec_key] = (effect_id, requirements)
effect_id, requirements = cache[imposed_spec_key]
self.gen.fact(fn.pkg_fact(named_cond.name, fn.condition_effect(condition_id, effect_id)))
return condition_id