fix(memhub): checkpoint 记录栈初始容量 64K→2M + realloc 失败诊断
单文件翻译(parse AST + 生成 IR)可产生几十万次 alloc,64K 初始容量 在首个大文件就触发 realloc 扩容;realloc 失败时该块不再记录到 checkpoint 栈 → reset_to 无法回收 → 渐进泄漏 → 1GB 主池 OOM (NewAstTest Phase2 Phase A 根因,used 精确到 2^30 吻合)。 初始容量加大到 2M 条目(16MB stdlib,惰性分配)覆盖单文件峰值, 避免扩容;realloc 失败分支打印 cap/depth 诊断(fail-fast 暴露而非 静默泄漏)。
This commit is contained in:
1 parent
50795b63f1
commit
31d7602368
1 file changed
+15
-7
+15
-7
@@ -362,14 +362,15 @@ class MemBuddy(MemManager):
|
||||
def mark(self) -> t.CSizeT:
|
||||
"""返回当前分配水位(checkpoint)
|
||||
|
||||
记录栈用 stdlib.malloc 分配(64K 条目 × 8B = 512KB,独立于 buddy 区),
|
||||
首次调用时懒分配。这样不占用 buddy 池、不会把 1GB 池砍半、
|
||||
reset_to 也不会误释放栈自身。
|
||||
记录栈用 stdlib.malloc 分配(独立于 buddy 区,避免占用 buddy 池、
|
||||
避免 reset_to 误释放栈自身,也避免栈内存与 buddy 块重叠)。
|
||||
初始容量 2M 条目(16MB):单文件翻译(parse AST + 生成 IR)可产生
|
||||
几十万次 alloc,64K 初始容量会在首个大文件就触发 realloc 扩容,
|
||||
扩容失败时块不再记录 → reset_to 永久 no-op → 所有分配泄漏 →
|
||||
1GB 主池 OOM(NewAstTest Phase2 根因)。
|
||||
"""
|
||||
if self.chk_stack is None:
|
||||
# 记录栈用 stdlib.malloc 分配(独立于 buddy 区,避免占用 buddy 池、
|
||||
# 避免 reset_to 误释放栈自身,也避免栈内存与 buddy 块重叠)。
|
||||
cap: t.CSizeT = 64 * 1024
|
||||
cap: t.CSizeT = 2 * 1024 * 1024
|
||||
base: t.CVoid | t.CPtr = t.CVoid(stdlib.malloc(cap * 8), t.CPtr)
|
||||
if base is None:
|
||||
return 0
|
||||
@@ -552,7 +553,7 @@ class MemBuddy(MemManager):
|
||||
c.DerefAs(t.CVoid(t.CUInt64T(block) + bs - MEMBUDDY_CANARY, t.CPtr),
|
||||
t.CVoid(_canary_pattern(), t.CPtr))
|
||||
# 记录到 checkpoint 栈(供 reset_to 回收)
|
||||
# 栈满时 stdlib.realloc 翻倍扩容(防 64K 爆满后记录缺失
|
||||
# 栈满时 stdlib.realloc 翻倍扩容(防爆满后记录缺失
|
||||
# → reset 不回收 + _is_valid_ptr 栈校验退化的连锁问题)
|
||||
if self.chk_stack is not None:
|
||||
if self.chk_depth >= self.chk_cap:
|
||||
@@ -563,6 +564,12 @@ class MemBuddy(MemManager):
|
||||
self.chk_base = new_stack
|
||||
self.chk_stack = (t.CUInt64T | t.CPtr)(t.CVoid(new_stack, t.CPtr))
|
||||
self.chk_cap = new_cap
|
||||
else:
|
||||
# realloc 失败:块不再记录 → reset_to 无法回收该块 →
|
||||
# 渐进泄漏最终 1GB 主池 OOM。fail-fast 暴露而非静默。
|
||||
stdio.printf(
|
||||
"[MEM] 记录栈 realloc 失败 cap=%zu depth=%zu(reset 将失效,终止)\n",
|
||||
self.chk_cap, self.chk_depth)
|
||||
if self.chk_depth < self.chk_cap:
|
||||
self.chk_stack[self.chk_depth] = t.CUInt64T(block)
|
||||
self.chk_depth += 1
|
||||
@@ -752,3 +759,4 @@ class MemBuddy(MemManager):
|
||||
return 6
|
||||
ci += 1
|
||||
return 0
|
||||
|
||||
Reference in new issue
Block a user