BIG speedup by caching the *set* of edge targets for a given key

This commit is contained in:
Joeri Exelmans 2024-10-28 17:11:55 +01:00
parent 38924237e1
commit a4352e3184
2 changed files with 38 additions and 0 deletions

View file

@ -122,6 +122,15 @@ class Bottom:
Returns: Returns:
List of UUIDs of outgoing edges List of UUIDs of outgoing edges
""" """
### PERFORMANCE OPTIMIZATION ###
if label != None:
fast_result = self.state.read_dict_edge_all(source, label)
# if set(alt) != set(edges):
# raise Exception("WRONG", alt, edges)
return fast_result
### PERFORMANCE OPTIMIZATION ###
def read_label(_edge: UUID): def read_label(_edge: UUID):
try: try:
label_edge, = self.state.read_outgoing(_edge) label_edge, = self.state.read_outgoing(_edge)
@ -136,6 +145,9 @@ class Bottom:
return [] return []
if label != None: if label != None:
edges = [e for e in edges if read_label(e) == label] edges = [e for e in edges if read_label(e) == label]
return edges return edges
def read_incoming_elements(self, target: UUID, label=None) -> List[UUID]: def read_incoming_elements(self, target: UUID, label=None) -> List[UUID]:

View file

@ -23,6 +23,8 @@ class PyState(State):
self.cache = {} self.cache = {}
self.cache_node = {} self.cache_node = {}
self.cache_all = {}
self.root = self.create_node() self.root = self.create_node()
def create_node(self) -> Node: def create_node(self) -> Node:
@ -46,6 +48,7 @@ class PyState(State):
dict_source, dict_target = self.edges[source] dict_source, dict_target = self.edges[source]
if target in self.values: if target in self.values:
self.cache.setdefault(dict_source, {})[self.values[target]] = source self.cache.setdefault(dict_source, {})[self.values[target]] = source
self.cache_all.setdefault(dict_source, {}).setdefault(self.values[target], set()).add(source)
self.cache_node.setdefault(dict_source, {})[target] = source self.cache_node.setdefault(dict_source, {})[target] = source
return new_id return new_id
@ -70,6 +73,7 @@ class PyState(State):
assert n != None and e != None assert n != None and e != None
e2 = self.create_edge(e, n) e2 = self.create_edge(e, n)
self.cache.setdefault(source, {})[value] = e self.cache.setdefault(source, {})[value] = e
self.cache_all.setdefault(source, {}).setdefault(value, set()).add(e)
self.cache_node.setdefault(source, {})[n] = e self.cache_node.setdefault(source, {})[n] = e
def read_root(self) -> Node: def read_root(self) -> Node:
@ -139,10 +143,31 @@ class PyState(State):
return first return first
# Hit but invalid now # Hit but invalid now
del self.cache[elem][value] del self.cache[elem][value]
self.cache_all[elem][value].remove(first)
return None return None
except KeyError: except KeyError:
return None return None
def read_dict_edge_all(self, elem: Element, value: Any) -> List[Edge]:
result = []
try:
all_ = self.cache_all[elem][value]
for a in all_:
try:
if ((self.edges[a][0] == elem) and (value in [self.values[self.edges[i][1]]
for i in self.outgoing[a]
if self.edges[i][1] in self.values])):
result.append(a)
continue
except KeyError:
pass
if len(result) != len(all_):
self.cache_all[elem][value] = set(result)
except KeyError:
pass
return result
def read_dict_node(self, elem: Element, value_node: Node) -> Optional[Element]: def read_dict_node(self, elem: Element, value_node: Node) -> Optional[Element]:
e = self.read_dict_node_edge(elem, value_node) e = self.read_dict_node_edge(elem, value_node)
if e == None: if e == None:
@ -273,6 +298,7 @@ class PyState(State):
dset.add(key) dset.add(key)
for key in dset: for key in dset:
del self.cache[key] del self.cache[key]
del self.cache_all[key]
dset = set() dset = set()
for key in self.cache_node: for key in self.cache_node: