[5.7] Avoid redundant checks in cycle detection #5847
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Dramatically improve speed of cycle detection for large or well-connected manifest graphs.
Motivation:
Loading a project with a large or well-connected package graph in Xcode can be very slow.
Xcode uses
Workspace.loadPackageGraph(rootPath:...)
, which calls intocalls into
findCycle()
.findCycle
has a bug leading to slower than linear cycle detection.Modifications:
There is a note to convert to use an algorithm tracking traversal with a stack, which would allow for linear time cycle detection. But given the output of
findCycle
is the path to first the cycle, and the cycle itself, not all the elements in a strongly connected subgraph, it's enough to memoize fully explored nodes.Once all of a Manifests outbound edges have been traversed for cycles, it's not possible for it to participate in a cycle. So if a fully-explored Manifest is encountered again in a cycle check, exit early.
Without such an early exit, cycle detection is slower than linear. This change makes it linear.
Result:
I made a tool to generate and profile the loading of package graphs through the same path as Xcode here.
These are the results of profiling package loading a small range of number of packages.