perf(diag): OOM 二分定位诊断 + 主池提升 1.5GB
BuildPipeline/Phase2/StmtGenMixin/HandlesAnnAssign 增加 [MEM] 限频打印 (parse/translate 前后、Phase A 前后、stmt 行级、AnnAssign 入口), 定位 NewAstTest 翻译内存暴涨起点;主池 1.5GB(2^30+2^29 二进制分解), 给单文件峰值与 Phase A 高并发翻译留足余量。
This commit is contained in:
1 parent
f9878e5a63
commit
0a0e6d3bab
5 files changed
+38
-5
No files matched your search
@@ -116,6 +116,8 @@ def TranslateFileGetTrans(mb: memhub.MemBuddy | t.CPtr, file_path: str,
|
||||
ast._lexer_init(lx, src_buf, mb)
|
||||
tokens: ast.Token | t.CPtr = ast.tokenize(lx)
|
||||
tree: ast.AST | t.CPtr = ast.parse_tokens(mb, tokens)
|
||||
# OOM 诊断:parse 后主池用量(区分 parse/translate/dump 阶段)
|
||||
stdio.printf("[MEM] TFGT parse后 used=%zu chk_depth=%zu\n", mb.used_bytes(), mb.chk_depth)
|
||||
# parse 完成后 AST 树已独立,释放源代码缓冲区(避免 1MB/文件泄漏)
|
||||
stdlib.free(src_buf)
|
||||
if tree is None:
|
||||
@@ -214,7 +216,11 @@ def TranslateFileGetTrans(mb: memhub.MemBuddy | t.CPtr, file_path: str,
|
||||
# 0xffffffffffffffff 崩溃),docstring 提取与翻译状态无关,提前安全。
|
||||
if gen is not None:
|
||||
gen.extract_module_docstrings(tree, sha1_val)
|
||||
# OOM 诊断:translate 前主池用量
|
||||
stdio.printf("[MEM] TFGT translate前 used=%zu chk_depth=%zu\n", mb.used_bytes(), mb.chk_depth)
|
||||
ret: int = tr.translate(tree)
|
||||
# OOM 诊断:translate 后主池用量(对比 translate 前 → translate 内部增长量)
|
||||
stdio.printf("[MEM] TFGT translate后 used=%zu chk_depth=%zu\n", mb.used_bytes(), mb.chk_depth)
|
||||
if ret != 0:
|
||||
fb_tf: str = VLogger.fmt_buf()
|
||||
if fb_tf is not None:
|
||||
|
||||
@@ -5,6 +5,7 @@ import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdlib
|
||||
import stdio
|
||||
import viperlib
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
@@ -78,6 +79,9 @@ class StmtGenMixin:
|
||||
EnumTable: HandlesEnum.EnumEntry | t.CPtr
|
||||
EnumCount: int
|
||||
|
||||
# --- OOM 语句级诊断计数(translate_stmt 限频打印 used) ---
|
||||
DiagStmtCount: int
|
||||
|
||||
# ============================================================
|
||||
# 簇 A:语句分派/流程语句(迁移自 HandlesBody.vp)
|
||||
# ============================================================
|
||||
@@ -87,6 +91,14 @@ class StmtGenMixin:
|
||||
"""翻译单条语句,返回新增的变量数"""
|
||||
if node is None:
|
||||
return 0
|
||||
# OOM 语句级诊断:每 10 语句打印主池用量+行号——定位单文件翻译
|
||||
# (NewAstTest main.vp)从 6.4MB 暴涨到 1.6GB 发生在哪一行
|
||||
self.DiagStmtCount += 1
|
||||
if (self.DiagStmtCount % 10) == 1:
|
||||
pool_diag: memhub.MemBuddy | t.CPtr = CompilerFactory.get_pool()
|
||||
stdio.printf("[MEM] stmt %d line %d used=%zu chk_depth=%zu\n",
|
||||
self.DiagStmtCount, node.lineno,
|
||||
pool_diag.used_bytes(), pool_diag.chk_depth)
|
||||
k: int = node.kind()
|
||||
|
||||
if k == ast.ASTKind.Expr:
|
||||
|
||||
@@ -420,6 +420,9 @@ class AnnAssignHandle(HandlesBase.Mixin):
|
||||
aa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(node)
|
||||
if aa is None:
|
||||
return 0
|
||||
# OOM 诊断:AnnAssign 入口 used(定位 Constant 构造语句的注解/值翻译段)
|
||||
stdio.printf("[MEM] AnnAssign.Handle line %d used=%zu chk=%zu\n",
|
||||
node.lineno, self.Trans.Pool.used_bytes(), self.Trans.Pool.chk_depth)
|
||||
|
||||
target: ast.AST | t.CPtr = aa.target
|
||||
if target is None or target.kind() != ast.ASTKind.Name:
|
||||
|
||||
@@ -552,6 +552,10 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
|
||||
stdlib.free(entries)
|
||||
return 1
|
||||
string.memset(done_flags, 0, file_count)
|
||||
# 二分诊断:Phase A 开始前主池用量——若已接近 1GB 说明
|
||||
# pre-inc/pre 阶段的 reset_to(mark2) 未回收(记录栈/realloc 失效);
|
||||
# 若用量低则泄漏发生在 Phase A 自身。
|
||||
stdio.printf("[MEM] Phase A 前主池 used=%zu\n", mb.used_bytes())
|
||||
PHASE_A_MAX_PASSES: t.CInt = 32
|
||||
for pass_a in range(PHASE_A_MAX_PASSES):
|
||||
completed_this_pass: int = 0
|
||||
@@ -560,6 +564,9 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
|
||||
continue
|
||||
ea: t.CUInt64T = t.CUInt64T(entries) + i * entry_size
|
||||
ent: SrcFileEntry | t.CPtr = (SrcFileEntry | t.CPtr)(t.CVoid(ea, t.CPtr))
|
||||
# OOM 二分诊断:翻译前 used —— 若逐文件递增 → reset_to(mark2) 未回收;
|
||||
# 若单文件翻译中暴涨 → 单文件瞬时峰值/泄漏(定位 Phase A OOM)
|
||||
stdio.printf("[MEM] PhaseA 翻译前 i=%d/%d used=%zu\n", i, file_count, mb.used_bytes())
|
||||
if ent is None or ent.Path is None:
|
||||
done_flags[i] = 1
|
||||
completed_this_pass += 1
|
||||
@@ -648,6 +655,9 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
|
||||
# OOM 清理:stub/text/deps 已写盘,回收本文件翻译瞬时数据
|
||||
# (AST/tokens/lexer/IR/Handler);app_deps_buf 已深拷贝依赖,不受影响
|
||||
mb.reset_to(mark2)
|
||||
# OOM 二分诊断:reset 后 used —— 应回落到 mark2 水位(3MB 级),
|
||||
# 若仍高 → reset 失效(记录栈缺失/coalesce 未归还)
|
||||
stdio.printf("[MEM] PhaseA 翻译后 reset i=%d/%d used=%zu\n", i, file_count, mb.used_bytes())
|
||||
# 收敛检查:所有文件完成则结束
|
||||
all_done: int = 1
|
||||
for i_ck in range(file_count):
|
||||
|
||||
+7
-5
@@ -49,15 +49,17 @@ import viperlib
|
||||
import hashlib
|
||||
|
||||
|
||||
# 内存大小: fl_bytes=264 (33*8), POOL_SIZE-fl_bytes 必须是 2 的幂以避免浪费
|
||||
# 1073742088 - 264 = 1073741824 (1024MB usable = 2^30)
|
||||
# 注意: POOL_SIZE 必须是 2^N+264,否则 _largest_pow2_le 会取低一级 2 的幂
|
||||
# 内存大小: fl_bytes=264 (33*8)。
|
||||
# 主池 1.5GB(1.5×2^30 + 264 = 1610613000):memhub 二进制分解为 2^30+2^29 两块。
|
||||
# 曾试 2GB(2^31+264):当前机器物理内存可用不足 1GB(已提交 76.6GB/81.3GB),
|
||||
# 主池 2GB + perm_pool 512MB = 2.5GB 提交导致 malloc 失败 → TPV 启动即退出。
|
||||
# 1.5GB + 512MB = 2GB 整提交,留 2.7GB 提交余量,稳妥且比 1.2GB 多 0.3GB。
|
||||
# Phase1 翻译 87 个 includes 文件 + Phase2 翻译 30 个测试文件,512MB 不足导致 Phase2 崩溃
|
||||
# 2026-08-13: NewAstTest 依赖 ast 模块(98 includes),Phase2 的 Phase A-pre-inc/Phase A
|
||||
# 无 mark/reset 回收,98 个 includes 的 AST/IR 全量累积 pool 超 1GB → 曾增大到 2GB。
|
||||
# → 已在 Phase2 对齐 Phase1 的 mark1/reset_to 清理机制(每文件翻译后回收瞬时数据),
|
||||
# 峰值回落至单文件水平,恢复 1GB(1073742088 - 264 = 1073741824 = 2^30)
|
||||
POOL_SIZE: t.CDefine = 1073742088
|
||||
# 峰值回落至单文件水平;1.5GB 主池给单文件峰值与 Phase A 高并发翻译留足余量。
|
||||
POOL_SIZE: t.CDefine = 1610613000
|
||||
# 永久内存池大小:2^29 + 264 = 512MB usable(存跨 mark 持久数据:泛型模板
|
||||
# 表/节点、struct/union/REnum 类型树、枚举 BaseTy、spec 缓存等)。
|
||||
# 与主 pool 独立(MemBuddy 第二实例),永不 reset_to,不占主 pool 配额。
|
||||
|
||||
Reference in new issue
Block a user