diff options
author | Daniel Silverstone <daniel.silverstone@codethink.co.uk> | 2019-05-30 13:41:36 +0100 |
---|---|---|
committer | Daniel Silverstone <daniel.silverstone@codethink.co.uk> | 2019-05-30 14:46:01 +0100 |
commit | ddd9c32c622786ed434e93e001196707b969bd1e (patch) | |
tree | 482c6ddee08741c2e7bff38b5610314f8df32f39 /src/buildstream | |
parent | 4ad986861bed89a23fc99dcf3e398e7fc9afbc94 (diff) | |
download | buildstream-ddd9c32c622786ed434e93e001196707b969bd1e.tar.gz |
loader.py: Make _collect_element() iterative
To reduce stack usage during load, make the LoadElement to MetaElement
conversion be iterative.
Signed-off-by: Daniel Silverstone <daniel.silverstone@codethink.co.uk>
Diffstat (limited to 'src/buildstream')
-rw-r--r-- | src/buildstream/_loader/loader.py | 55 |
1 files changed, 41 insertions, 14 deletions
diff --git a/src/buildstream/_loader/loader.py b/src/buildstream/_loader/loader.py index 13b2d1213..161a8cc08 100644 --- a/src/buildstream/_loader/loader.py +++ b/src/buildstream/_loader/loader.py @@ -449,18 +449,17 @@ class Loader(): element.dependencies.sort(key=cmp_to_key(dependency_cmp)) - - # _collect_element() + # _collect_element_no_deps() # - # Collect the toplevel elements we have + # Collect a single element, without its dependencies, into a meta_element # # Args: # element (LoadElement): The element for which to load a MetaElement # # Returns: - # (MetaElement): A recursively loaded MetaElement + # (MetaElement): A partially loaded MetaElement # - def _collect_element(self, element): + def _collect_element_no_deps(self, element): # Return the already built one, if we already built it meta_element = self._meta_elements.get(element.name) if meta_element: @@ -502,17 +501,45 @@ class Loader(): # Cache it now, make sure it's already there before recursing self._meta_elements[element.name] = meta_element - # Descend - for dep in element.dependencies: - loader = dep.element._loader - meta_dep = loader._collect_element(dep.element) - if dep.dep_type != 'runtime': - meta_element.build_dependencies.append(meta_dep) - if dep.dep_type != 'build': - meta_element.dependencies.append(meta_dep) - return meta_element + # _collect_element() + # + # Collect the toplevel elements we have + # + # Args: + # top_element (LoadElement): The element for which to load a MetaElement + # + # Returns: + # (MetaElement): A fully loaded MetaElement + # + def _collect_element(self, top_element): + element_queue = [top_element] + meta_element_queue = [self._collect_element_no_deps(top_element)] + + while element_queue: + element = element_queue.pop() + meta_element = meta_element_queue.pop() + + for dep in element.dependencies: + + loader = dep.element._loader + name = dep.element.name + + if name not in loader._meta_elements: + meta_dep = loader._collect_element_no_deps(dep.element) + element_queue.append(dep.element) + meta_element_queue.append(meta_dep) + else: + meta_dep = loader._meta_elements[name] + + if dep.dep_type != 'runtime': + meta_element.build_dependencies.append(meta_dep) + if dep.dep_type != 'build': + meta_element.dependencies.append(meta_dep) + + return self._meta_elements[top_element.name] + # _get_loader(): # # Return loader for specified junction |