ITADN

objectpath performance

#385Openewhauser 创建于 2026-01-04
E
ewhausercommented
### Summary nilaway's use of `objectpath.Encoder.For()` in the primitivizer causes significant allocation pressure on large codebases, resulting in high GC overhead. ### Problem When analyzing packages with many exported types, nilaway calls `objectpath.Encoder.For()` frequently to compute stable identifiers for cross-package inference. Profiling on a large monorepo (~9000 packages) showed: - `objectpath` functions consumed **504MB (60%)** of allocations on hot packages - GC overhead was **~40% of CPU time** (`gcDrain` + `scanobject`) ### Current Mitigation We added a cache in `primitivizer.site()` to avoid redundant `objPathEncoder.For()` calls for the same `types.Object`: ```go objPath, cached := p.objPathCache[obj] if !cached { objPath, err = p.objPathEncoder.For(obj) // ... p.objPathCache[obj] = objPath } ``` This helps but doesn't reduce per-call allocation overhead within objectpath itself. ### Upstream Fix I've filed an issue with golang.org/x/tools to add `sync.Pool` for path buffers and finder structs: - **Issue:** https://github.com/golang/go/issues/77059 With the upstream fix applied: | Metric | Before | After | Improvement | |--------|--------|-------|-------------| | Allocations | 929MB | 445MB | **52% reduction** | | GC cycles | 21 | 14 | **33% reduction** | | CPU on GC | ~40% | <5% | **~90% reduction** | ### Suggestion Once the upstream fix lands in x/tools, nilaway should update its dependency to benefit from the reduced allocations. In the meantime, the `objPathCache` in primitivizer provides partial mitigation. /cc @yuxincs
3 条评论