diff --git a/App/lib/core/BuildPipeline.vp b/App/lib/core/BuildPipeline.vp index c159ab7..acd2e98 100644 --- a/App/lib/core/BuildPipeline.vp +++ b/App/lib/core/BuildPipeline.vp @@ -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: diff --git a/App/lib/core/Gen/StmtGenMixin.vp b/App/lib/core/Gen/StmtGenMixin.vp index 6cf6bec..b4038b3 100644 --- a/App/lib/core/Gen/StmtGenMixin.vp +++ b/App/lib/core/Gen/StmtGenMixin.vp @@ -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: diff --git a/App/lib/core/Handles/HandlesAnnAssign.vp b/App/lib/core/Handles/HandlesAnnAssign.vp index d7c5e11..fca9f03 100644 --- a/App/lib/core/Handles/HandlesAnnAssign.vp +++ b/App/lib/core/Handles/HandlesAnnAssign.vp @@ -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: diff --git a/App/lib/core/Phase2.vp b/App/lib/core/Phase2.vp index ce8e2bc..6e23c08 100644 --- a/App/lib/core/Phase2.vp +++ b/App/lib/core/Phase2.vp @@ -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): diff --git a/App/main.vp b/App/main.vp index 1a87803..cd2cc74 100644 --- a/App/main.vp +++ b/App/main.vp @@ -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 配额。