[analyze deps] Also show cycle islands.

We currently display a list of all minimal cycles, but it's
useful to be able to see the big picture impact of these cycles
by merging them all together into groups of interconnected
components.

Because the cycle discovery algorithm only considers "minimal"
cycles, it discards all information for dependencies which are
not considered part of the minimal cycle.  So all we know is that
the components of each island definitely all depend on each other
but it's still possible that there are hidden dependencies due
to transitive includes.

The cycle list should still be the authoritative reference for
deciding where the easiest places to break cycles are, though.

llvm-svn: 298530
This commit is contained in:
Zachary Turner 2017-03-22 18:04:20 +00:00
parent d07d155ebb
commit 84a6218fbe
1 changed files with 14 additions and 0 deletions

View File

@ -105,6 +105,7 @@ def expand(path_queue, path_lengths, cycles, src_map):
next_len = path_lengths.pop(0) + 1 next_len = path_lengths.pop(0) + 1
last_component = cur_path[-1] last_component = cur_path[-1]
for item in src_map[last_component]: for item in src_map[last_component]:
if item.startswith("clang"): if item.startswith("clang"):
continue continue
@ -177,5 +178,18 @@ if args.discover_cycles:
for cycle in cycles: for cycle in cycles:
cycle.append(cycle[0]) cycle.append(cycle[0])
print " -> ".join(cycle) print " -> ".join(cycle)
print "Analyzing islands..."
islands = []
for cycle in cycles:
this_cycle = set(cycle)
disjoints = [x for x in islands if this_cycle.isdisjoint(x)]
overlaps = [x for x in islands if not this_cycle.isdisjoint(x)]
islands = disjoints + [set.union(this_cycle, *overlaps)]
print "Found {} disjoint cycle islands...".format(len(islands))
for island in islands:
print "Island ({} elements)".format(len(island))
for node in island:
print " {0}".format(node)
sys.stdout.flush() sys.stdout.flush()
pass pass