perf(memhub): 活跃块校验改为仅 --detection 生效,消除 free 的 O(N) 扫描

_is_valid_ptr 的 live-set 检查会对 chk_stack 线性扫描(长度 = chk_depth)。PermPool 永不 reset,窗口单调增长到数百万条,类型驻留开始归还缓冲后每次 free 都扫描整个窗口,使 PhaseA 单文件翻译退化到分钟级。该检查与 --detection 同级(诊断用),改为仅在检测模式执行;生产路径仍靠头部奇偶位拒绝重复 free,保持 O(1)。
This commit is contained in:
TermiNexus committed 2026-10-24 12:48:25 +08:00
1 parent 53c1b2d373
commit 7b95e16bf8
1 file changed
+9 -6
+9 -6
View File
@@ -1444,12 +1444,15 @@ class MemBuddy(MemManager):
order: int = int(stored_val >> 1)
if order < 0: return 0
if order > self.max_order: return 0
# Live-set check: every alloc pushes its block onto chk_stack, and reset_to(mark)
# pops [mark, chk_depth) and frees those blocks. A stale pointer with a still-odd
# header would pass the checks above, so require the block to sit in the live
# window [0, chk_depth). Once chk_stack is full (chk_depth == chk_cap) new blocks
# are no longer recorded, so the check is skipped to avoid rejecting valid frees.
if self.chk_stack is not None and self.chk_depth < self.chk_cap:
# Live-set check (diagnostic, --detection only): every alloc pushes its block onto
# chk_stack, and reset_to(mark) pops [mark, chk_depth) and frees those blocks. A stale
# pointer with a still-odd header would pass the checks above, so require the block to
# sit in the live window [0, chk_depth). The scan is O(chk_depth): a pool that is never
# reset (PermPool) grows the window without bound (5M entries observed), so running it on
# every free made the type-interning frees O(N^2) and stretched one file's translation to
# minutes. The check is the same class of aid as --detection, so it is gated on it; the
# production path stays O(1) and still rejects re-frees via the header parity test above.
if self.detection != 0 and self.chk_stack is not None and self.chk_depth < self.chk_cap:
alive: int = 0
for ci in range(int(self.chk_depth)):
if self.chk_stack[ci] == uint64(block):