[WIP] feat: mmap-based package summary cache format (internal/meta)#1989
Draft
luoliwoshang wants to merge 36 commits into
Draft
[WIP] feat: mmap-based package summary cache format (internal/meta)#1989luoliwoshang wants to merge 36 commits into
luoliwoshang wants to merge 36 commits into
Conversation
# Conflicts: # internal/build/build.go # ssa/abitype.go
… format
Introduces internal/meta, a new binary format and read/write layer for
LLGo's whole-program DCE package summary cache (.meta files).
Key design decisions:
- Zero-copy reads via mmap: PackageMeta is a thin view over a mmap'd byte
slice; Edges, TypeChildren, MethodSlots and IfaceMethods all use
unsafe.Slice to reinterpret the on-disk bytes directly, with no alloc.
- CSR layout (Compressed Sparse Row): each per-symbol section stores an
offsets[nsyms+1] prefix array and a flat data array, matching the design
used by Go's own goobj format (BlkRelocIdx + BlkReloc).
- Single allocation on write: Builder.Build() pre-computes all section sizes
and offsets in one pass, allocates one []byte, then writes every section
directly at its target offset — no intermediate buffers, no seek-back.
- Lazy remap in GlobalSummary: merging N PackageMetas only interns the
string tables (O(unique_symbols)); edges and type-children are translated
lazily on query, avoiding the O(total_edges) rewrite cost of the MVP.
- NameRef for method names: method short names are stored as {Off, Len}
pairs referencing the string table, keeping them distinct from module-level
symbols (LocalSymbol) while still enabling cross-package matching via
global Name interning in GlobalSummary.
- Compile-time layout assertions: const expressions verify sizeof(Edge)==12,
sizeof(MethodSlot)==20, sizeof(MethodSig)==12 so any struct drift that
would break the zero-copy reinterpretation fails at build time.
Sections in the .meta wire format:
stringTable | Symbols | Edges (CSR) | TypeChildren (CSR) |
MethodInfo (CSR) | InterfaceInfo (CSR) | ReflectBitmap
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace the MVP's uvarint-based metadata format with the new mmap-based zero-copy format (internal/meta). All read paths use unsafe reinterpretation of on-disk bytes; write paths use single-allocation serialization. Key changes: - ssa/cl: switch metaBuilder from *metadata.Builder to *meta.Builder; AddIfaceMethod/AddTypeChild now deduplicate internally - internal/build: wire cache miss/hit paths to meta.ReadMeta/Build/WriteMeta - internal/deadcode: analyze.go uses meta.GlobalSummary with GMethodSlot (flat struct, no nested .Sig) - internal/meta: add zero-copy SymbolName/NameString via unsafe.String, add typeChildrenSet map for O(1) dedup, add FormatMeta for golden tests - cl/_testmeta: update 9 golden files to new deterministic sort order Perf (etcd client demo, 334 packages): summary merge: 114.7ms → ~23ms (5x faster via lazy remap + zero-copy strings) DCE analyze: ~34ms unchanged total: ~148ms → ~52ms (2.8x faster) Co-Authored-By: Claude <noreply@anthropic.com>
Remove Phase 2 eager translation — instead of scanning every type in all 334 packages and translating all ~10080 method slots up front, only mark concrete/interface type kinds in Phase 1 (cheap CSR range checks, no slot translation). MethodSlots() and InterfaceMethods() now translate lazily on first access and cache the result. DCE typically reaches only ~500 of ~10000+ types, so lazy translation avoids thousands of unnecessary pm.NameString + internName calls. Perf (etcd client demo, 334 packages): merge: 115ms → ~18ms (6.4x faster) total: ~149ms → ~48ms (3.1x faster) Co-Authored-By: Claude <noreply@anthropic.com>
4 tasks
a21246b to
9861150
Compare
PackageMeta query methods are now all lowercase (private). External code interacts only through GlobalSummary, Builder, ReadMeta, Bytes, and Close. - Drop IsConcreteType, IsInterface, IsCompositeType — callers use nmethodSlot/ntypeChild/nifaceMethod count methods instead - Add N-prefix count methods (Go goobj convention): nedge, ntypeChild, nmethodSlot, nifaceMethod — single CSR range check, no unsafe pointer - All CSR accessors share csrSlice[T] generic helper, eliminating repeated CSR+unsafe pointer boilerplate - Remove NSyms() method — same-package callers use pm.nsyms field - Remove NewPackageMetaFromBytes — no external callers - Make buildMethodImplKeys fully lazy: concrete type methodImplKeys are computed on-demand in flood's usedInIface path; only methodRefs reverse index is built eagerly - MetaString → String() (fmt.Stringer) — zero additional public API - Drop ConcreteTypes() from GlobalSummary; isConcrete tracking removed from Phase 1 Co-Authored-By: Claude <noreply@anthropic.com>
# Conflicts: # chore/gentests/gentests.go # cl/compile_test.go # internal/build/collect_test.go # ssa/expr.go # ssa/interface.go
Contributor
Author
|
TestBCD 这个发现在Iface调用点再emit interfaceInfo会导致定义包没有emit interface,使用包要interface,事实错乱,应该修改为定义包emit这个事实 |
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR introduces
internal/meta, a new binary format and read/write layer for LLGo's whole-program DCE package summary cache (.metafiles). It replaces the MVP's uvarint-encoded format with a zero-copy mmap design modeled after Go's owncmd/internal/goobjformat.PackageMetais a thin view over a mmap'd byte slice;Edges,TypeChildren,MethodSlots, andIfaceMethodsuseunsafe.Sliceto reinterpret on-disk bytes directly — no deserialization, no allocation.offsets[nsyms+1]prefix array and a flat data array (same pattern as Go'sBlkRelocIdx + BlkReloc), giving O(1) per-symbol access.Builder.Build()pre-computes all section sizes/offsets in one pass, allocates one[]byte, and writes each section directly at its target offset — no intermediate buffers.GlobalSummary: merging N packages only interns string tables (O(unique_symbols)); edges, type-children, method slots and interface methods are all translated lazily on query. DCE typically reaches ~500 of ~10000+ types, avoiding thousands of unnecessary translations.constexpressions pinsizeof(Edge)==12,sizeof(MethodSlot)==20,sizeof(MethodSig)==12so any struct drift that breaks zero-copy reinterpretation fails at build time.SymbolName()andNameString()useunsafe.Stringto return strings pointing directly into the mmap region — no allocation on the hot path.Wire format sections
Performance
Status
Builder— accumulates facts, serializes to wire formatPackageMeta— mmap view, zero-copy CSR queriesGlobalSummary— lazy remap merge, global Symbol/Name spacesinternal/deadcode) to newGlobalSummaryinternal/build)Test plan
TestRoundTrip— in-memory Builder → PackageMeta round-tripTestRoundTripFile— write to disk → ReadMeta (mmap) round-tripTestTypeChildrenAlignment— padding + zero-copy correctness across 5 string table lengthsTestWireLayout— struct size and field offset assertionsTestGlobalSummaryMerge— cross-package lazy edge translation, method name unificationTestGlobalSummaryLinkonce— first-wins dedup for linkonce type descriptors🤖 Generated with Claude Code