Skip to content

[5.7] Avoid redundant checks in cycle detection #5847

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Nov 30, 2022

Conversation

fcanas
Copy link
Contributor

@fcanas fcanas commented Oct 27, 2022

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 into
calls 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.

Number of packages apple/spm memoized
22 17.9s 0.2s
23 35.8s 0.2s
24 88.1s 0.2s
25 160.5s 0.2s
26 323.4s 0.2s

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 quadratic. This change makes it linear.

Convert tabs to spaces

Fix indentation

Add performance test for Workspace package loading

Don't disable error propagation

Move test to PackageGraph and remove fixtures
@MaxDesiatov
Copy link
Contributor

@swift-ci please smoke test

@fcanas
Copy link
Contributor Author

fcanas commented Oct 27, 2022

My mistake. The tests need adjustment from the main branch version.

I'll push a fix soon.

@MaxDesiatov
Copy link
Contributor

@swift-ci please smoke test

@tomerd tomerd enabled auto-merge (squash) October 27, 2022 19:58
@MaxDesiatov
Copy link
Contributor

@swift-ci please smoke test

@tomerd tomerd added the 5.7 label Oct 27, 2022
@tomerd tomerd changed the title Avoid redundant checks in cycle detection [5.7] Avoid redundant checks in cycle detection Oct 27, 2022
@tomerd tomerd disabled auto-merge October 28, 2022 00:24
@fcanas
Copy link
Contributor Author

fcanas commented Nov 1, 2022

@tomerd Is there anything else I can do to move this change along?

@tomerd
Copy link
Contributor

tomerd commented Nov 1, 2022

thanks @fcanas, the 5.7 release process is carefully managed. we will merge this if / when there is an opportunity to take it forward

@tomerd tomerd merged commit bf28632 into swiftlang:release/5.7 Nov 30, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants