-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Paralellize retrieving resolved packages #8220
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
Conversation
| ) | ||
| default: | ||
| throw InternalError("invalid resolved package type \(resolvedPackage.packageRef.kind)") | ||
| await withThrowingTaskGroup(of: Void.self) { taskGroup in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Returning back the parallelization of retrieving resolved packages
|
|
||
| /// Represents the workspace internal state persisted on disk. | ||
| public final class WorkspaceState { | ||
| public actor WorkspaceState { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Making WorkspaceState into actor to make it thread-safe
| extension Workspace { | ||
| /// A collection of managed dependencies. | ||
| final public class ManagedDependencies { | ||
| public struct ManagedDependencies { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Turning ManagedDependencies into a struct. The alternative would be to make it an actor but since it conforms to Collection, it wouldn't be that easy.
There are only two methods of ManagedDependencies that are mutable – add and remove. Instead of mutating self, we can return copy of Self and do the mutation in WorkspaceState.
| public func add(dependency: Workspace.ManagedDependency) { | ||
| dependencies = dependencies.add(dependency) | ||
| } | ||
|
|
||
| public func remove(identity: PackageIdentity) { | ||
| dependencies = dependencies.remove(identity) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To keep the setter of dependencies private, we need to add helper methods for the two operations that mutate ManagedDependencies. Alternatively, we could make the setter public, however, I do find this makes callsites of WorkspaceState consumers nicer, so I'm leaning to keep the current solution.
|
I ran, from the root of the repository, the following shell script against this PR and there were no entries in the associated |
|
Thanks for checking @bkhouri. I believe then the previous thread-safety issues should be fixed now 🙏 cc @dschaefer2 |
|
I added the utility script in #8227 |
|
Also, we did some performance testing of this branch at https://github.com/tuist/registry-tests using some real-world Here's some of the relevant data we gathered: Measurement dataPackage 1 (41 dependencies)Source control with Swift 6.0.3Registry with Swift 6.0.3Source: https://github.com/tuist/registry-tests/actions/runs/12785286884/job/35643544361#step:6:760 Source control using swift-package from this branch
Registry using swift-package from this branch
Package 2 (63 dependencies)Source control with Swift 6.0.3Registry with Swift 6.0.3Source control using swift-package from this branch
Registry using swift-package from this branch
|
|
@fortmarek Have you tried executing all of the swift tests on your change? Maybe it's me, but I'm seeing a few test failures when running |
|
Thanks @bkhouri! I don't think it has to do anything with running the tests in parallel, but some |
|
@bkhouri the issue should be fixed – |
|
@swift-ci please test macos linux |
|
Hey @bkhouri, sorry the longer silence here. Would you mind re-running the CI – I updated the branch with the latest changes from |
|
@swift-ci please test |
|
Looks like all CI tests are passing now, too. Let me know if there's anything else I can do to push this PR forward 🙂 |
|
Hey @bkhouri @plemarquand @MaxDesiatov – sorry for the broad ping, but would love to see this get in 🙏 |
|
@swift-ci test |
|
This seems to be passing on CI 🚀 |
MaxDesiatov
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With this PR as is, the relationship between SwiftCommand and AsyncSwiftCommand becomes unclear, they essentially duplicate each other with this change.
|
Thanks @MaxDesiatov for your feedback, should be resolved now 🙏 |
MaxDesiatov
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, but I'd like this to get at least one review from someone on the SwiftPM team before merging.
|
@swift-ci test |
|
@swift-ci test windows |
2 similar comments
|
@swift-ci test windows |
|
@swift-ci test windows |
plemarquand
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great to me! Just one minor comment, otherwise its good to go.
|
@swift-ci test |
|
@swift-ci test windows |
|
@swift-ci test windows |
|
@fortmarek thanks for this great contribution! Looking forward to the improvements it brings. |
Paralellize retrieving resolved packages
Motivation:
This PR brings back the parallelization reverted here.
As raised in the revertal, checkouts and registry downloads mutate the
WorkspaceState– and running these operations in parallel can lead to a crash since theWorkspaceStateis not thread-safe.Modifications:
Based on this suggestion, I'm making
WorkspaceStateanactorto make access to it thread-safe.Additionally, I turned
ManagedDependenciesinto astructto ensure its thread-safety, too. There are two methods of this struct that mutate self –addandremove. I changed this to return a new copy ofManagedDependenciesinstead and add counterpart methods inWorkspaceStatewhere the mutation is done in-place. SinceManagedDependenciesis aCollection, making it into anactorbecause of two mutable methods didn't feel like the right fit. However, let me know what you think about it.I added comments to the key modifications to make it easier to find the more interesting modifications since there's a lot of noise since I had to add loads of
asyncandawait. You can find these comments below.Result:
Retrieving resolved packages in parallel should not lead to crashes.
As suggested by @bkhouri here, I ran
WorkspaceTestsmultiple times to see if I run into any thread-safety issues: