perf(memhub): detection 采样探测,O(n²) 降为 O(n²/256)
每次 alloc 全表扫描(分配重叠 + _det_probe)是 O(n) ,2M 次 alloc = O(n²),detection 模式过慢。 改为每 MEMBUDDY_DET_PROBE_PERIOD(256) 次 alloc 采样扫描一次;记录追加保持 O(1)。损坏是持久性的,不依赖即时扫描,检测能力不损失。
This commit is contained in:
1 parent
b777d7c925
commit
7c7629852a
1 file changed
+26
-15
+26
-15
@@ -47,6 +47,11 @@ MEMBUDDY_FILL_PATTERN: t.CDefine = 0xCD
|
||||
MEMBUDDY_DET_MARKER: t.CDefine = 0xCDCD
|
||||
# 检测记录区默认大小(32MB,每条记录 {ptr u64, size u64} = 16B)
|
||||
MEMBUDDY_DET_RECORD_SIZE: t.CDefine = 33554432
|
||||
# 采样周期(2 的幂):每 N 次 alloc 做一次全表扫描(分配重叠 + 探测)。
|
||||
# 记录追加本身 O(1) 不受影响;损坏是持久性的,不依赖即时扫描,采样
|
||||
# 不损失检测能力——2M 次 alloc 若每次全表 O(n) 扫描 = O(n²) 太慢
|
||||
# (用户反馈 detection 模式过慢),采样把扫描次数降为 1/N。
|
||||
MEMBUDDY_DET_PROBE_PERIOD: t.CDefine = 256
|
||||
|
||||
|
||||
def _canary_pattern() -> t.CUInt64T:
|
||||
@@ -674,20 +679,25 @@ class MemBuddy(MemManager):
|
||||
m_t_d: t.CUInt16T | t.CPtr = (t.CUInt16T | t.CPtr)(t.CVoid(tail_d, t.CPtr))
|
||||
m_t_d[0] = t.CUInt16T(MEMBUDDY_DET_MARKER)
|
||||
if self._det_records is not None:
|
||||
# 分配重叠即时检测:新块地址是否已在 active 记录(同一块重复
|
||||
# 分配实锤——SlotsBugTest 7B buf 与 72B Token 同 ptr、cargs
|
||||
# 只写 0/40 根因)。重叠 = MemBuddy free list 损坏(active 块
|
||||
# 混入 free list),在第一次重叠处拦截并打印两个 size。
|
||||
ff_d: t.CUInt64T = t.CUInt64T(1) << 63
|
||||
dup_i: t.CSizeT = 0
|
||||
while dup_i < self._det_count:
|
||||
drp: t.CUInt64T = self._det_records[dup_i * 2]
|
||||
drs: t.CUInt64T = self._det_records[dup_i * 2 + 1]
|
||||
if drp == base_ret_d + 2 and (drs & ff_d) == 0:
|
||||
stdio.printf("[DET] 分配重叠: 新alloc(size=%llu)与记录[%zu](sz=%llu)同地址 ptr=%llu(同一块重复分配,free list 损坏)\n",
|
||||
t.CUInt64T(size), dup_i, drs & (ff_d - 1), base_ret_d + 2)
|
||||
stdlib.exit(1)
|
||||
dup_i += 1
|
||||
# 采样:每 MEMBUDDY_DET_PROBE_PERIOD 次 alloc 做一次全表扫描
|
||||
# (分配重叠 + 探测),其余只追加记录(O(1))。损坏是持久性的,
|
||||
# 不依赖即时扫描——2M 次 alloc 若每次全表 O(n) = O(n²) 太慢
|
||||
# (用户反馈 detection 模式过慢),采样把扫描降为 O(n²/PERIOD)。
|
||||
if (self._det_count & (MEMBUDDY_DET_PROBE_PERIOD - 1)) == 0:
|
||||
# 分配重叠即时检测:新块地址是否已在 active 记录(同一块重复
|
||||
# 分配实锤——SlotsBugTest 7B buf 与 72B Token 同 ptr、cargs
|
||||
# 只写 0/40 根因)。重叠 = MemBuddy free list 损坏(active 块
|
||||
# 混入 free list),在第一次重叠处拦截并打印两个 size。
|
||||
ff_d: t.CUInt64T = t.CUInt64T(1) << 63
|
||||
dup_i: t.CSizeT = 0
|
||||
while dup_i < self._det_count:
|
||||
drp: t.CUInt64T = self._det_records[dup_i * 2]
|
||||
drs: t.CUInt64T = self._det_records[dup_i * 2 + 1]
|
||||
if drp == base_ret_d + 2 and (drs & ff_d) == 0:
|
||||
stdio.printf("[DET] 分配重叠: 新alloc(size=%llu)与记录[%zu](sz=%llu)同地址 ptr=%llu(同一块重复分配,free list 损坏)\n",
|
||||
t.CUInt64T(size), dup_i, drs & (ff_d - 1), base_ret_d + 2)
|
||||
stdlib.exit(1)
|
||||
dup_i += 1
|
||||
if self._det_count >= self._det_cap:
|
||||
# 记录表满:stdlib.realloc 翻倍扩容(防 is_alive/_det_probe
|
||||
# 因容量耗尽漏检——SlotsBugTest 编译 includes 超 2M 次 alloc,
|
||||
@@ -703,7 +713,8 @@ class MemBuddy(MemManager):
|
||||
self._det_records[self._det_count * 2] = base_ret_d + 2
|
||||
self._det_records[self._det_count * 2 + 1] = t.CUInt64T(size)
|
||||
self._det_count += 1
|
||||
self._det_probe()
|
||||
if (self._det_count & (MEMBUDDY_DET_PROBE_PERIOD - 1)) == 0:
|
||||
self._det_probe()
|
||||
result = t.CVoid(base_ret_d + 2, t.CPtr)
|
||||
if result is None:
|
||||
# 分配失败诊断(定位"异常 size/池耗尽导致 None → 调用方解引用段错误")
|
||||
|
||||
Reference in new issue
Block a user