Omit fake edge to root
This saves singificant time in comparison Signed-off-by: Todd Gamblin <tgamblin@llnl.gov>
This commit is contained in:
parent
8363fbf40f
commit
485291ef20
@ -3815,8 +3815,7 @@ def _cmp_iter(self):
|
|||||||
# 2. A generator over canonical edges
|
# 2. A generator over canonical edges
|
||||||
#
|
#
|
||||||
# Canonical edges have consistent ids defined by breadth-first traversal order. That is,
|
# Canonical edges have consistent ids defined by breadth-first traversal order. That is,
|
||||||
# the fake edge from nothing to the root is (0, 1), the root is always 1, dependencies of
|
# the root is always 0, dependencies of the root are 1, 2, 3, etc., and so on.
|
||||||
# the root are 2, 3, 4, 5, etc., and so on.
|
|
||||||
#
|
#
|
||||||
# The three cases are:
|
# The three cases are:
|
||||||
#
|
#
|
||||||
@ -3839,19 +3838,14 @@ def _cmp_iter(self):
|
|||||||
# need for the complexity here. It was not clear at the time of writing that how
|
# need for the complexity here. It was not clear at the time of writing that how
|
||||||
# much optimization was possible in `spack.traverse`.
|
# much optimization was possible in `spack.traverse`.
|
||||||
|
|
||||||
def yield_root_edge():
|
|
||||||
yield 0 # id of None (parent of root)
|
|
||||||
yield 1 # id of root
|
|
||||||
yield 0 # depflag on fake edge
|
|
||||||
yield () # virtuals on fake edge
|
|
||||||
|
|
||||||
if not self._dependencies:
|
if not self._dependencies:
|
||||||
# Spec has no dependencies -- simplest case
|
# Spec has no dependencies -- simplest case
|
||||||
def nodes():
|
def nodes():
|
||||||
yield self._cmp_node # just yield this node
|
yield self._cmp_node # just yield this node
|
||||||
|
|
||||||
def edges():
|
def edges():
|
||||||
yield yield_root_edge
|
return
|
||||||
|
yield
|
||||||
|
|
||||||
elif not any(
|
elif not any(
|
||||||
dep.spec._dependencies for deplist in self._dependencies.values() for dep in deplist
|
dep.spec._dependencies for deplist in self._dependencies.values() for dep in deplist
|
||||||
@ -3879,15 +3873,12 @@ def nodes():
|
|||||||
yield edge.spec._cmp_node
|
yield edge.spec._cmp_node
|
||||||
|
|
||||||
def edges():
|
def edges():
|
||||||
# yield root edge consistent with what traverse would do.
|
|
||||||
yield yield_root_edge
|
|
||||||
|
|
||||||
# we've already sorted to yield dependency nodes in order, now yield
|
# we've already sorted to yield dependency nodes in order, now yield
|
||||||
# edges for comparison in the same order, with BFS-consistent ids
|
# edges for comparison in the same order, with BFS-consistent ids
|
||||||
for i, edge in enumerate(sorted_edges, start=2):
|
for i, edge in enumerate(sorted_edges, start=1):
|
||||||
|
|
||||||
def yield_edge(i=i, edge=edge):
|
def yield_edge(i=i, edge=edge):
|
||||||
yield 1 # id of root
|
yield 0 # id of root
|
||||||
yield i # id of dependency in BFS order
|
yield i # id of dependency in BFS order
|
||||||
yield edge.depflag
|
yield edge.depflag
|
||||||
yield edge.virtuals
|
yield edge.virtuals
|
||||||
@ -3900,7 +3891,6 @@ def yield_edge(i=i, edge=edge):
|
|||||||
# We need a way to compare edges consistently between two arbitrary specs.
|
# We need a way to compare edges consistently between two arbitrary specs.
|
||||||
# node_ids generates consistent node ids based on BFS traversal order.
|
# node_ids generates consistent node ids based on BFS traversal order.
|
||||||
node_ids = collections.defaultdict(lambda: len(node_ids))
|
node_ids = collections.defaultdict(lambda: len(node_ids))
|
||||||
node_ids[id(None)] # None (parent of root) is always node id 0
|
|
||||||
|
|
||||||
# To avoid traversing twice, we put edges in this list as we yield the nodes.
|
# To avoid traversing twice, we put edges in this list as we yield the nodes.
|
||||||
# edges() yields the edge functions later, if necessary.
|
# edges() yields the edge functions later, if necessary.
|
||||||
@ -3915,6 +3905,10 @@ def nodes():
|
|||||||
yield edge.spec._cmp_node
|
yield edge.spec._cmp_node
|
||||||
node_ids[id(edge.spec)]
|
node_ids[id(edge.spec)]
|
||||||
|
|
||||||
|
# skip fake edge to root
|
||||||
|
if edge.parent is None:
|
||||||
|
continue
|
||||||
|
|
||||||
# create "edges" with the ids we generated above
|
# create "edges" with the ids we generated above
|
||||||
def yield_edge(edge=edge):
|
def yield_edge(edge=edge):
|
||||||
yield node_ids[id(edge.parent)]
|
yield node_ids[id(edge.parent)]
|
||||||
|
@ -2057,10 +2057,7 @@ def test_spec_ordering(specs_in_expected_order):
|
|||||||
"spec,expected_tuplified",
|
"spec,expected_tuplified",
|
||||||
[
|
[
|
||||||
# simple, no dependencies
|
# simple, no dependencies
|
||||||
[
|
[("a"), ((("a", None, EMPTY_VER, EMPTY_VAR, EMPTY_FLG, None, None, None),), ())],
|
||||||
("a"),
|
|
||||||
((("a", None, EMPTY_VER, EMPTY_VAR, EMPTY_FLG, None, None, None),), ((0, 1, 0, ()),)),
|
|
||||||
],
|
|
||||||
# with some node attributes
|
# with some node attributes
|
||||||
[
|
[
|
||||||
("a@1.0 +foo cflags='-O3 -g'"),
|
("a@1.0 +foo cflags='-O3 -g'"),
|
||||||
@ -2077,7 +2074,7 @@ def test_spec_ordering(specs_in_expected_order):
|
|||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
((0, 1, 0, ()),),
|
(),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
# single edge case
|
# single edge case
|
||||||
@ -2088,7 +2085,7 @@ def test_spec_ordering(specs_in_expected_order):
|
|||||||
("a", None, EMPTY_VER, EMPTY_VAR, EMPTY_FLG, None, None, None),
|
("a", None, EMPTY_VER, EMPTY_VAR, EMPTY_FLG, None, None, None),
|
||||||
("b", None, EMPTY_VER, EMPTY_VAR, EMPTY_FLG, None, None, None),
|
("b", None, EMPTY_VER, EMPTY_VAR, EMPTY_FLG, None, None, None),
|
||||||
),
|
),
|
||||||
((0, 1, 0, ()), (1, 2, 0, ())),
|
((0, 1, 0, ()),),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
# root with multiple deps
|
# root with multiple deps
|
||||||
@ -2101,7 +2098,7 @@ def test_spec_ordering(specs_in_expected_order):
|
|||||||
("c", None, EMPTY_VER, EMPTY_VAR, EMPTY_FLG, None, None, None),
|
("c", None, EMPTY_VER, EMPTY_VAR, EMPTY_FLG, None, None, None),
|
||||||
("d", None, EMPTY_VER, EMPTY_VAR, EMPTY_FLG, None, None, None),
|
("d", None, EMPTY_VER, EMPTY_VAR, EMPTY_FLG, None, None, None),
|
||||||
),
|
),
|
||||||
((0, 1, 0, ()), (1, 2, 0, ()), (1, 3, 0, ()), (1, 4, 0, ())),
|
((0, 1, 0, ()), (0, 2, 0, ()), (0, 3, 0, ())),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
# root with multiple build deps
|
# root with multiple build deps
|
||||||
@ -2114,7 +2111,7 @@ def test_spec_ordering(specs_in_expected_order):
|
|||||||
("c", None, EMPTY_VER, EMPTY_VAR, EMPTY_FLG, None, None, None),
|
("c", None, EMPTY_VER, EMPTY_VAR, EMPTY_FLG, None, None, None),
|
||||||
("d", None, EMPTY_VER, EMPTY_VAR, EMPTY_FLG, None, None, None),
|
("d", None, EMPTY_VER, EMPTY_VAR, EMPTY_FLG, None, None, None),
|
||||||
),
|
),
|
||||||
((0, 1, 0, ()), (1, 2, dt.BUILD, ()), (1, 3, dt.BUILD, ()), (1, 4, dt.BUILD, ())),
|
((0, 1, dt.BUILD, ()), (0, 2, dt.BUILD, ()), (0, 3, dt.BUILD, ())),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
# dependencies with dependencies
|
# dependencies with dependencies
|
||||||
@ -2132,12 +2129,11 @@ def test_spec_ordering(specs_in_expected_order):
|
|||||||
),
|
),
|
||||||
(
|
(
|
||||||
(0, 1, 0, ()),
|
(0, 1, 0, ()),
|
||||||
(1, 2, 0, ()),
|
(0, 2, 0, ()),
|
||||||
(1, 3, 0, ()),
|
(1, 3, dt.BUILD, ()),
|
||||||
(2, 4, dt.BUILD, ()),
|
(1, 4, dt.BUILD, ()),
|
||||||
(2, 5, dt.BUILD, ()),
|
(2, 5, dt.BUILD, ()),
|
||||||
(3, 6, dt.BUILD, ()),
|
(2, 6, dt.BUILD, ()),
|
||||||
(3, 7, dt.BUILD, ()),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
Loading…
Reference in New Issue
Block a user