Skip to content

build: use loaded package metadata for assembly files - #2412

Merged
xushiwei merged 2 commits into
xgo-dev:mainfrom
zhouguangyuan0718:codex/client-go-loaded-sfiles
Aug 26, 2026
Merged

build: use loaded package metadata for assembly files#2412
xushiwei merged 2 commits into
xgo-dev:mainfrom
zhouguangyuan0718:codex/client-go-loaded-sfiles

Conversation

@zhouguangyuan0718

Copy link
Copy Markdown
Contributor

Summary

  • use the assembly files already selected by the package loader instead of running a second go list
  • retain .s/.S, test-assembly, synthetic test-main, and internal/chacha8rand handling
  • add a regression test that makes any second go list invocation fail

This fixes the k8s.io/client-go@v0.36.2 root-package compile gap from the LLGo compatibility suite. Dependencies loaded from the module cache remain tied to the original module/workspace context, rather than being queried again from a dependency directory.

Compatibility result: https://xgo-dev.github.io/benchmarks/compatibility.html

Verification

  • go test ./internal/build -run 'Test(SelectedSFiles|PkgSFiles|ShouldSkipPlan9AsmSFiles)' -count=1
  • go test ./internal/build -count=1
  • go vet ./internal/build
  • llgo test -short k8s.io/client-go in a module pinned to k8s.io/client-go@v0.36.2 (PASS)

@fennoai fennoai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review summary

Clean, well-motivated refactor. pkgSFiles no longer spawns a go list -json subprocess per package; instead it derives assembly files from the already-loaded pkg.OtherFiles (populated by packages.Load with the target GOOS/GOARCH). This removes a fork/exec + JSON parse per package, drops the encoding/json and os/exec imports, and simplifies selectedSFiles. Doc comments and tests were updated to match, and the tests even set an empty PATH to prove no subprocess runs.

I verified the core assumption: packages.Load with NeedFiles and the per-target GOOS/GOARCH env returns OtherFiles already filtered to the build target (confirmed internal/chacha8rand yields only chacha8_amd64.s on GOOS=linux GOARCH=amd64), so dropping the subprocess is behavior-preserving. The .s/.S extension filter added to selectedSFiles is correct since OtherFiles also contains .c/.h/etc. The new len(paths) != 0 guard on the chacha8rand branch is a small correctness improvement.

Findings are minor / non-blocking — see inline comments.

Findings without inline locations

  • internal/build/collect.go:200: Possible duplicate digest entries (observation, likely pre-existing). pkgSFiles now returns paths taken directly from p.OtherFiles, and those same .s paths are already present in otherFiles (which starts as a copy of p.OtherFiles). digestFilesWithOverlay does not deduplicate, so each selected assembly file gets digested twice into the fingerprint's OtherFiles. I believe this pre-dates the PR (the old filepath.Join(lp.Dir, f) produced the same absolute paths), and the result stays deterministic because the digest list is sorted — so it's harmless but redundant. Worth confirming whether the double-count is intended; if not, dedup before digestFilesWithOverlay.

Comment thread internal/build/plan9asm.go Outdated
if len(paths) != 0 && pkg.PkgPath == "internal/chacha8rand" && pkg.Dir != "" {
stub := filepath.Join(pkg.Dir, "chacha8_stub.s")
if _, err := os.Stat(stub); err == nil {
paths := []string{stub}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shadowed paths (minor). paths := []string{stub} declares a new variable that shadows the outer paths accumulator. It's correct here only because both the cache write and the return sit inside this block, but the shadow is unnecessary and forces a reader to check the scope. Prefer a plain assignment paths = []string{stub} (drop the :=) or a distinct name like stubPaths.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in f7059c1: reuse the outer paths variable.

Comment thread internal/build/plan9asm.go Outdated
// tail-jumps to block_generic and preserves package behavior.
if pkg.PkgPath == "internal/chacha8rand" && lp.Dir != "" {
stub := filepath.Join(lp.Dir, "chacha8_stub.s")
if len(paths) != 0 && pkg.PkgPath == "internal/chacha8rand" && pkg.Dir != "" {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant pkg.Dir != "" (minor). pkgSFiles already returns early when pkg.Dir == "" (a few lines above), so pkg.Dir is guaranteed non-empty here. In the old code this clause checked lp.Dir from the JSON output (a different value); after the refactor it's a dead condition and can be dropped. A one-line comment noting that len(paths) != 0 intentionally scopes the stub override to targets that actually select chacha8 asm would also help future readers not "simplify" the guard away.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in f7059c1: removed the redundant pkg.Dir guard and documented why the selected-path guard is intentional.

@codecov

codecov Bot commented Aug 25, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@github-actions

github-actions Bot commented Aug 25, 2026

Copy link
Copy Markdown

LLGo baseline benchmarks

f7059c1fa498 | workflow run | long-term charts

Program measurements

Platform Workload File size vs base Text size vs base Build vs base Run vs base
Linux cprintf 19256 B 0 B / +0.0% 387 B 0 B / +0.0% 333.359 ms +5.88 ms / +1.8% (worse) 1.354 ms -112.2 us / -7.6% (better)
Linux cprintf-lto 19088 B 0 B / +0.0% 368 B 0 B / +0.0% 344.538 ms +3.272 ms / +1.0% (worse) 1.378 ms +41.63 us / +3.1% (worse)
Linux fmtprintf 1653224 B 0 B / +0.0% 501083 B 0 B / +0.0% 2.485 s -302.5 ms / -10.9% (better) 3.627 ms -65.52 us / -1.8% (better)
Linux fmtprintf-lto 1525824 B 0 B / +0.0% 459700 B 0 B / +0.0% 8.505 s -211.4 ms / -2.4% (better) 3.531 ms +88.12 us / +2.6% (worse)
Linux println 62032 B 0 B / +0.0% 15261 B 0 B / +0.0% 337.947 ms +6.291 ms / +1.9% (worse) 1.722 ms +9.414 us / +0.5% (worse)
Linux println-lto 53840 B 0 B / +0.0% 12882 B 0 B / +0.0% 508.091 ms +3.596 ms / +0.7% (worse) 1.725 ms -48.34 us / -2.7% (better)
macOS cprintf 84480 B 0 B / +0.0% 16493 B 0 B / +0.0% 344.028 ms +21.37 ms / +6.6% (worse) 2.227 ms +144.9 us / +7.0% (worse)
macOS cprintf-lto 100704 B 0 B / +0.0% 16473 B 0 B / +0.0% 427.931 ms -28.89 ms / -6.3% (better) 2.783 ms +353.5 us / +14.5% (worse)
macOS fmtprintf 1498256 B 0 B / +0.0% 882133 B 0 B / +0.0% 1.892 s -384.8 ms / -16.9% (better) 4.947 ms -485.4 us / -8.9% (better)
macOS fmtprintf-lto 1208976 B 0 B / +0.0% 875129 B 0 B / +0.0% 5.040 s -343.1 ms / -6.4% (better) 5.628 ms +877.2 us / +18.5% (worse)
macOS println 114832 B 0 B / +0.0% 34849 B 0 B / +0.0% 454.028 ms +128.8 ms / +39.6% (worse) 2.953 ms +71.5 us / +2.5% (worse)
macOS println-lto 118656 B 0 B / +0.0% 32489 B 0 B / +0.0% 458.619 ms +15.77 ms / +3.6% (worse) 2.765 ms -74.21 us / -2.6% (better)
Core language and compiler benchmarks
Platform Benchmark ns/op vs base
Linux BenchmarkLookupPCRandom 12.290 ns/op +0.03 ns/op / +0.2% (worse)
Linux BenchmarkMergeCompilerFlags 144.400 ns/op +0.2 ns/op / +0.1% (worse)
Linux BenchmarkMergeLinkerFlags 94.040 ns/op +0.25 ns/op / +0.3% (worse)
Linux BenchmarkChannelBuffered 37.640 ns/op +0.04 ns/op / +0.1% (worse)
Linux BenchmarkChannelHandoff 23798 ns/op -349 ns/op / -1.4% (better)
Linux BenchmarkDefer 49.480 ns/op +0.11 ns/op / +0.2% (worse)
Linux BenchmarkDirectCall 1.758 ns/op -0.001 ns/op / -0.1% (better)
Linux BenchmarkGlobalRead 2.111 ns/op +0.001 ns/op / +0.04739% (worse)
Linux BenchmarkGlobalWrite 2.808 ns/op -0.005 ns/op / -0.2% (better)
Linux BenchmarkGoroutine 29273 ns/op -5246 ns/op / -15.2% (better)
Linux BenchmarkInterfaceCall 9.417 ns/op +0.135 ns/op / +1.5% (worse)
Linux BenchmarkRuntimeGetG 2.112 ns/op +0.001 ns/op / +0.04737% (worse)
macOS BenchmarkLookupPCRandom 12.810 ns/op +1.45 ns/op / +12.8% (worse)
macOS BenchmarkMergeCompilerFlags 153.900 ns/op +40.9 ns/op / +36.2% (worse)
macOS BenchmarkMergeLinkerFlags 111.300 ns/op +42.41 ns/op / +61.6% (worse)
macOS BenchmarkChannelBuffered 24.960 ns/op -0.33 ns/op / -1.3% (better)
macOS BenchmarkChannelHandoff 9182 ns/op +2696 ns/op / +41.6% (worse)
macOS BenchmarkDefer 32.170 ns/op +1.2 ns/op / +3.9% (worse)
macOS BenchmarkDirectCall 1.050 ns/op +0.0769 ns/op / +7.9% (worse)
macOS BenchmarkGlobalRead 1.061 ns/op +0.0806 ns/op / +8.2% (worse)
macOS BenchmarkGlobalWrite 1.201 ns/op +0.2035 ns/op / +20.4% (worse)
macOS BenchmarkGoroutine 22448 ns/op -2202 ns/op / -8.9% (better)
macOS BenchmarkInterfaceCall 5.150 ns/op +0.434 ns/op / +9.2% (worse)
macOS BenchmarkRuntimeGetG 2.106 ns/op +0.109 ns/op / +5.5% (worse)

Compared with 1f8cd64c94af measured in the same runner job.

@xushiwei
xushiwei merged commit 2dea863 into xgo-dev:main Aug 26, 2026
43 checks passed
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