-
Notifications
You must be signed in to change notification settings - Fork 133
Remove build_plan from lockfile to improve perf #1362
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
base: master
Are you sure you want to change the base?
Conversation
|
This is a breaking change, in that |
|
Code looks good, though 👍 |
fsoikin
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.
There is also a comment that refers to storing all transitive dependencies in the lockfile:
spago/src/Spago/Command/Fetch.purs
Lines 162 to 164 in 782311b
| -- We compute the transitive deps for all the packages in the workspace, but keep them | |
| -- split by package - we need all of them so we can stash them in the lockfile, but we | |
| -- are going to only download the ones that we need to, if e.g. there's a package selected |
I also noticed that there is a copy&paste of computing transitive deps for all workspace packages - here and here. Perhaps these should be consolidated?
| getDeps :: PackageName -> Set PackageName | ||
| getDeps name = case Map.lookup name lockfile.workspace.packages of | ||
| Just pkg -> Set.fromFoldable $ Map.keys $ unwrap pkg.core.dependencies | ||
| Nothing -> Set.fromFoldable $ case Map.lookup name lockfile.packages of | ||
| Just (FromPath { dependencies }) -> dependencies | ||
| Just (FromGit { dependencies }) -> dependencies | ||
| Just (FromRegistry { dependencies }) -> dependencies | ||
| Nothing -> [] | ||
|
|
||
| transitiveClosure :: Set PackageName -> Set PackageName | ||
| transitiveClosure initial = go initial initial | ||
| where | ||
| allWorkspacePackages = Map.fromFoldable $ map (\p -> Tuple p.package.name (WorkspacePackage p)) (Config.getWorkspacePackages workspace.packageSet) | ||
|
|
||
| isInBuildPlan :: forall v. PackageName -> v -> Boolean | ||
| isInBuildPlan name _package = Set.member name bp | ||
|
|
||
| workspacePackagesWeNeed = Map.filterWithKey isInBuildPlan allWorkspacePackages | ||
| otherPackages = map fromLockEntry $ Map.filterWithKey isInBuildPlan lockfile.packages | ||
| go seen new | ||
| | Set.isEmpty new = seen | ||
| | otherwise = | ||
| let | ||
| discovered = foldMap getDeps new `Set.difference` seen | ||
| in | ||
| go (seen <> discovered) discovered | ||
|
|
||
| computeTransitiveDeps :: Dependencies -> PackageMap | ||
| computeTransitiveDeps deps = | ||
| let | ||
| transitiveDeps = transitiveClosure $ Set.fromFoldable $ Map.keys $ unwrap deps | ||
|
|
||
| isInTransitiveDeps :: forall v. PackageName -> v -> Boolean | ||
| isInTransitiveDeps name _ = Set.member name transitiveDeps | ||
| in | ||
| Map.union | ||
| (Map.filterWithKey isInTransitiveDeps allWorkspacePackages) | ||
| (map fromLockEntry $ Map.filterWithKey isInTransitiveDeps lockfile.packages) |
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.
I don't quite understand why all of this is necessary.
Before this change, the transitive dependencies used to be initially calculated in the Left branch of this case, and then written to the lockfile, and subsequently lifted from there. This suggests that the logic for computing them already exists in some form inside the Left branch.
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.
It does, and I tried to unify it, but I now think that the two logics are different enough that it's not worth unifying them: the algo in question is in the Left branch and only in the case of a package set build (since otherwise the solver build is using the solver to get the transitive closure, which is different logic).
The overall algorithm is the same, but when solving a package set build one has effects, caches, and error reporting (since the plan build might fail).
We have none of that when we build a plan from the lockfile, so we can get away with much simpler implementation, even though the logic is overall the same.
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.
Ok, I see
Co-authored-by: Fyodor Soikin <name.fa@gmail.com>
Fix #1262 by following the approach I explained at the time - we remove
build_planfrom each package of the lockfile since it's faster to recompute it than to decode it, as the files can get massive.cc @finnhodgkin