From cf098a1d4f96de3494c9aa79491d1167b6a99aa7 Mon Sep 17 00:00:00 2001 From: JianFeeeee Date: Thu, 10 Sep 2026 14:33:44 +0800 Subject: [PATCH] =?UTF-8?q?feat(shm):=20arena=20allocator=20for=20unified?= =?UTF-8?q?=20region=20(=C2=A713.2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - SuperBlock 新增 arenaOff/arenaCap/arenaUsed 字段 - arenaAlloc: append-only bump 分配,offset 0 保留给空语义 - arenaWrite: 写入并返回 SharedRef(含 generation) - arenaRead: 按 SharedRef 切片读取 - arenaReset: 压实后重置游标 --- internal/plugin/proc/unified.go | 94 +++++++++++++++++++++++++++++---- 1 file changed, 84 insertions(+), 10 deletions(-) diff --git a/internal/plugin/proc/unified.go b/internal/plugin/proc/unified.go index 02611b5..3c1969c 100644 --- a/internal/plugin/proc/unified.go +++ b/internal/plugin/proc/unified.go @@ -62,8 +62,17 @@ const ( sbOffCtxSize = 24 sbOffEvtOff = 28 sbOffEvtSize = 32 + sbOffArenaOff = 36 // 动态 arena 起始偏移 + sbOffArenaCap = 40 // 动态 arena 总容量 + sbOffArenaUsed = 44 // 动态 arena 已用字节(原子) + sbOffReserved5 = 48 + sbOffReserved6 = 52 + sbOffReserved7 = 56 + sbOffReserved8 = 60 ) +const unifiedArenaSize = 256 * 1024 // 默认动态 arena 256KB + // SharedRef 是跨进程共享内存描述符,替代内联 JSON 数据。 // // 所有数据交换(工具调用参数/结果、Cleaner、输入/输出通道消息) @@ -99,6 +108,10 @@ type unifiedRegion struct { ctxSize uint32 evtOff uint32 evtSize uint32 + + arenaOff uint32 // 动态 arena 起始偏移(相对 data) + arenaCap uint32 // 动态 arena 总容量 + arenaUsed *uint32 // 指向 SuperBlock 中的 arenaUsed 字段(原子 bump 游标) } // initUnifiedRegion 在 mmap 区域上初始化 SuperBlock + 两个 segment。 @@ -111,6 +124,8 @@ func initUnifiedRegion(data []byte, ctxTotal, evtTotal int) (*unifiedRegion, err ctxOff := uint32(superBlockSize) evtOff := ctxOff + uint32(ctxTotal) + arenaOff := evtOff + uint32(evtTotal) + arenaCap := cap - arenaOff putU32(data[sbOffMagic:], unifiedMagic) putU32(data[sbOffVersion:], unifiedVersion) @@ -120,13 +135,21 @@ func initUnifiedRegion(data []byte, ctxTotal, evtTotal int) (*unifiedRegion, err putU32(data[sbOffCtxSize:], uint32(ctxTotal)) putU32(data[sbOffEvtOff:], evtOff) putU32(data[sbOffEvtSize:], uint32(evtTotal)) + putU32(data[sbOffArenaOff:], arenaOff) + putU32(data[sbOffArenaCap:], arenaCap) + putU32(data[sbOffArenaUsed:], 1) return &unifiedRegion{ - data: data, - ctxOff: ctxOff, - ctxSize: uint32(ctxTotal), - evtOff: evtOff, - evtSize: uint32(evtTotal), + data: data, + ctxOff: ctxOff, + ctxSize: uint32(ctxTotal), + evtOff: evtOff, + evtSize: uint32(evtTotal), + arenaOff: arenaOff, + arenaCap: arenaCap, + arenaUsed: (*uint32)(unsafe.Pointer( + uintptr(unsafe.Pointer(&data[0])) + uintptr(sbOffArenaUsed), + )), }, nil } @@ -148,16 +171,24 @@ func attachUnifiedRegion(data []byte) (*unifiedRegion, error) { evtOff := getU32(data[sbOffEvtOff:]) evtSize := getU32(data[sbOffEvtSize:]) + arenaOff := getU32(data[sbOffArenaOff:]) + arenaCap := getU32(data[sbOffArenaCap:]) + if int(evtOff)+int(evtSize) > len(data) { return nil, fmt.Errorf("unified: EvtRing 越界(off=%d size=%d total=%d)", evtOff, evtSize, len(data)) } return &unifiedRegion{ - data: data, - ctxOff: ctxOff, - ctxSize: ctxSize, - evtOff: evtOff, - evtSize: evtSize, + data: data, + ctxOff: ctxOff, + ctxSize: ctxSize, + evtOff: evtOff, + evtSize: evtSize, + arenaOff: arenaOff, + arenaCap: arenaCap, + arenaUsed: (*uint32)(unsafe.Pointer( + uintptr(unsafe.Pointer(&data[0])) + uintptr(sbOffArenaUsed), + )), }, nil } @@ -210,3 +241,46 @@ func getU64(b []byte) uint64 { return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 } + +// arenaAlloc 在动态 arena 中分配 n 字节,返回相对 arenaOff 的偏移。 +// append-only,offset 0 保留给“空”语义。 +func (r *unifiedRegion) arenaAlloc(n int) (uint32, error) { + if n <= 0 { + return 0, fmt.Errorf("arena: 非法分配长度 %d", n) + } + used := atomic.LoadUint32(r.arenaUsed) + if used == 0 { + used = 1 + } + end := uint64(used) + uint64(n) + if end > uint64(r.arenaCap) { + return 0, fmt.Errorf("arena: 空间不足(需 %d,剩 %d)", n, uint64(r.arenaCap)-uint64(used)) + } + atomic.StoreUint32(r.arenaUsed, uint32(end)) + return used, nil +} + +// arenaWrite 把 b 写入动态 arena 并返回 SharedRef。 +func (r *unifiedRegion) arenaWrite(b []byte) (SharedRef, error) { + if len(b) == 0 { + return SharedRef{}, nil + } + off, err := r.arenaAlloc(len(b)) + if err != nil { + return SharedRef{}, err + } + base := r.arenaOff + off + copy(r.data[base:base+uint32(len(b))], b) + gen := uint32(r.generation()) + return SharedRef{Offset: base, Length: uint32(len(b)), Generation: gen}, nil +} + +// arenaRead 按 SharedRef 读取数据。 +func (r *unifiedRegion) arenaRead(ref SharedRef) []byte { + return ref.Slice(r.data) +} + +// arenaReset 压实后重置游标(仅在无活跃 slot 时调用)。 +func (r *unifiedRegion) arenaReset() { + atomic.StoreUint32(r.arenaUsed, 1) +}