build: plan package dependency levels - #2177
Conversation
There was a problem hiding this comment.
Review summary
This is a clean, well-staged refactor toward bounded parallel compilation. The extraction of packageBuildSpec/packageBuildResult, the preflight/execute/finalize split, and the register-then-build separation for SSA packages are clear and well-tested. The llssaInitOnce guard and eager initializePackageBuildState are good defensive moves ahead of parallelism, and effectiveDependencies correctly closes a latent stale-cache hole (alt-package imports were previously not fingerprinted). The concurrent SSA worker pool in buildSSAPkgs is correct: worker count is bounded, the channel/WaitGroup pattern is leak-free, packages are de-duplicated, and fixSSAOrder is correctly kept serial.
A few points worth addressing (details inline):
-
Scaffolding computed on every build but unused in production.
newPackageBuildPlanbuildsdeps,byID, and the topologicallevels(internal/build/package_build.go:84-175), butbuildAllPkgsconsumes onlyplan.specs;levels/deps/byIDare read only from tests. This is intentional per the PR title, but the full O(V+E) leveling + allocations run on every build for a result nothing consumes yet. Consider documenting thatlevelsdoes not yet drive execution, or deferring it until the consuming scheduler lands, so future readers don't assume it controls build order. SimilarlypackageBuildResult.spec/archiveFile/cacheHitare currently write-only in production. -
Data-race caveat for the follow-up executor.
initializePackageBuildStateeagerly initializescacheManager/llvmVersion, butctx.built(written inpreflightPackageBuild) andctx.sfilesCacheremain plain maps with unguarded read/write. They are safe only because the package pipeline is still serial today; they must be guarded or sharded beforebuildOnePackage/the backend is parallelized. Worth a note so it isn't overlooked.
No blocking issues.
| count += len(level) | ||
| } | ||
| if count != len(p.specs) { | ||
| return nil, fmt.Errorf("package build dependency cycle") |
There was a problem hiding this comment.
The cycle error names no packages, making it hard to diagnose. Since effectiveDependencies now merges alt-package imports into the edge set, an alt package that (transitively) imports the package it patches can form a cycle that previously never failed the build — and this error is reachable from production Do() even though levels is otherwise unused. Consider including the involved package IDs in the message so a real regression here is diagnosable, and confirm no existing alt-package arrangement in the tree trips it.
| continue | ||
| } | ||
| parallel, err = strconv.Atoi(value) | ||
| if err != nil || parallel <= 0 { |
There was a problem hiding this comment.
Two minor points on -p validation:
- No upper bound: any positive int is accepted (e.g.
-p=2147483647). The SSA worker count is capped bymin(parallelism, len(unique))so goroutines are bounded by package count, but the value is also forwarded togo/packagesuncapped. A defensive clamp (e.g. toruntime.NumCPU()or a fixed ceiling) would close the theoretical resource-exhaustion angle. -p=0is rejected here, whileConfig.Parallel == 0is documented as valid ("Zero uses GOMAXPROCS") and accepted byDo. The two entry points disagree on whether0is legal. Rejecting0at the CLI is defensible (Go does too), but a one-line comment noting this would avoid confusion.
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
901065d to
da465b3
Compare
da465b3 to
f66d10e
Compare
f66d10e to
697eb43
Compare
|
Closing as obsolete after the architecture review: LLVM package backends no longer wait on dependency levels. The dependency-DAG/ready-level scheduler has been removed from the consolidated implementation. |
Summary
Validation
GOCACHE=/private/tmp/llgo-pr3-gocache go test ./internal/build ./internal/goflags ./cmd/internal/flags -count=1Dependency
This PR includes and depends on #2174, #2175, and #2176. Merge/rebase it after those PRs; it will then contain only this dependency-plan stage.