堆内存泄漏检测技能

385485 80129 更新时间: 2026-07-15 13:35:06

堆内存泄漏检测技能是OpenClaw平台提供的一款专业工具,用于自动化检测和诊断应用程序中的堆内存泄漏问题。该技能通过分析内存分配与释放模式,识别未释放的内存块,帮助开发者快速定位内存泄漏源头,优化程序性能。适用于C/C++、Rust等需要手动管理内存的语言项目,以及大型长期运行的服务器应用。核心特点包括:自动扫描堆内存操作、生成泄漏报告、支持自定义检测规则、集成到CI/CD流水线。使用场景包括代码审查、性能调优、稳定性测试等。

安装
bunx skills add https://github.com/openclaw/openclaw --skill openclaw-test-heap-leaks
技能详情 readonly

一、技能概述

该技能用于调查 pnpm test 运行时的内存增长、Vitest OOM、RSS 峰值以及堆快照差异。它通过系统化的取证工作流,避免仅凭 RSS 数值进行猜测

核心原则:将快照名称差异视为分类证据而非结论,直到 retainers(引用链)或 dominators(支配树)分析支持该判断


二、核心功能

1. 测试内存取证工作流(Test Memory Forensics)

技能提供了一套完整的内存问题复现与诊断流程:

复现问题

pnpm canvas:a2ui:bundle && \
OPENCLAW_TEST_MEMORY_TRACE=1 \
OPENCLAW_TEST_HEAPSNAPSHOT_INTERVAL_MS=60000 \
OPENCLAW_TEST_HEAPSNAPSHOT_DIR=.tmp/heapsnap \
OPENCLAW_TEST_WORKERS=2 \
OPENCLAW_TEST_MAX_OLD_SPACE_SIZE_MB=6144 \
pnpm test
  • 保持 OPENCLAW_TEST_MEMORY_TRACE=1 启用,使 wrapper 在生成快照的同时打印每个文件的 RSS 摘要

  • 如果报告涉及特定的 shard 或 worker 预算,保留该形状进行复现

识别真实 lane 名称

  • 从 [test-parallel] start ... 行或 pnpm test --plan 中获取真实的 lane 名称

  • 不要假设只有一个 unit-fast lane——本地计划通常会拆分为 unit-fast-batch-* 等多个 lane

等待多次快照

  • 至少从同一个 lane 采集两次间隔快照

  • 比较同一个 PID 在真实 lane 目录(如 .tmp/heapsnap/unit-fast-batch-2/)内的快照

2. 堆快照对比工具

技能提供了专用的对比脚本:

直接比较两个文件

node .agents/skills/openclaw-test-heap-leaks/scripts/heapsnapshot-delta.mjs before.heapsnapshot after.heapsnapshot

自动选择每个 PID 的最早/最新快照

node .agents/skills/openclaw-test-heap-leaks/scripts/heapsnapshot-delta.mjs --lane-dir .tmp/heapsnap/unit-fast-batch-2

常用参数

  • --top 40 —— 显示前 40 个差异最大的对象

  • --min-kb 32 —— 忽略小于 32KB 的差异

  • --pid 16133 —— 指定特定 PID 进行分析

分析优先级:先读取正向增长最大的条目——模块转换产物的巨大正向增长指向 lane 隔离问题;运行时对象的巨大正向增长指向真实泄漏。如果名称本身不足以判断,在 DevTools 中打开同一对快照,检查 retainers/dominators 后再声明根因

3. 内存增长分类

技能提供了清晰的分类框架:

增长类型 特征 处理方式
保留模块图增长 被 Vite/Vitest 转换的源字符串、Module、system/Context、bytecode、descriptor arrays、property maps 主导 通常是长期存活 worker 中的模块图保留问题
真实泄漏 被应用对象、缓存、buffers、server handles、timers、mock state、sqlite state 等运行时对象主导 查找缺失的 afterEach/afterAll、模块重置缺口、残留的全局状态、未释放的 DB handles 或存活过文件的 listeners/timers

如果名称模棱两可,停止做出自信的判断,在 DevTools 中检查 retainers/dominators

4. 修复策略

对于保留模块图增长

  • 优先通过 timing 和 hotspot 驱动的调度修复

  • 检查文件是否已在 test/fixtures/test-timings.unit.json 中体现

  • 仅在 timing-driven peeling 不足时,更新 test/fixtures/test-parallel.behavior.json

  • 对于单独运行安全但会膨胀共享 worker 堆的文件,优先使用 singletonIsolated

  • 如果文件本应已被 timings 剥离但不在 test/fixtures/test-timings.unit.json 中,明确指出

对于真实泄漏

  • 修补涉及的测试或运行时清理路径

  • 查找缺失的 afterEach/afterAll、模块重置缺口、残留的全局状态、未释放的 DB handles 或存活过文件的 listeners/timers

  • 用最直接的证据验证修复

5. 运行时修复验证(Runtime Fixes Validation)

上述工作流用于诊断 Vitest worker 内存增长。对于验证运行时/闭包修复是否真正释放了捕获的状态,使用专用测试工具

pnpm leak:embedded-run

该工具运行 scripts/embedded-run-abort-leak.ts,在模拟 runEmbeddedAttempt 的函数作用域中循环执行 N 次 abort 运行,写入堆快照,并通过 FinalizationRegistry 进行跟踪实例计数 + RSS delta 报告 PASS/FAIL 结论

三种模式

  • closure-extracted(默认)—— 生产修复形态(模块作用域的 helper)

  • closure-inline —— 修复前形态(runner 作用域内的闭包),用作敏感性检查

  • synthetic-leak —— 通过模块级 bucket 故意保留,用于确认 harness 能检测泄漏

快照落在 .tmp/embedded-run-abort-leak/,使用同样的脚本进行对比


三、主要用途

  1. 诊断 Vitest OOM 和 RSS 峰值
    当 pnpm test 因内存不足失败或 RSS 持续增长时,系统化地定位根因

  2. 区分真实泄漏与模块图保留
    通过堆快照对比和分类框架,避免将 worker-lifetime 问题误判为应用程序对象泄漏

  3. 验证运行时闭包修复
    使用 pnpm leak:embedded-run 专用 harness 验证闭包/运行时修复是否真正释放了捕获状态

  4. 优化测试调度
    通过识别 hotspot 文件和更新 timings manifest,将内存密集型文件移出共享 worker lane

  5. PR 审查中的内存回归证明
    在涉及内存敏感变更的 PR 中,提供快照对比证据支撑审查决策


四、重要原则

  1. 不凭 RSS 数值下结论:堆快照可用时,不要仅凭 RSS 猜测

  2. 快照名称差异是分类证据,不是结论:需要 retainers/dominators 支持才能下定论

  3. 不要将所有增长都称为泄漏unit-fast 或 unit-fast-batch-* 的大幅增长可能是 worker-lifetime 问题,而非应用程序对象泄漏

  4. 信任快照胜过直觉:当同一个 worker PID 中相同保留对象家族跨多个间隔增长时,信任快照,然后用 retainers 证据确认模糊的判断

  5. 先检查真实 lane 名称:不要假设单一的 unit-fast lane

  6. 等待至少两次间隔快照:再下结论

  7. 运行时修复使用专用 harness:不要用测试内存取证工作流验证运行时闭包修复


五、输出要求

使用该技能后,报告必须包含

  • 精确的复现命令

  • 比较了哪个 lane 和 PID

  • 快照差异中主导的保留对象家族

  • 问题是真实泄漏还是共享 worker 保留模块增长,以及 retainers/dominators 是否确认了该判断

  • 具体的修复或影响削减补丁

  • 验证了什么,以及快照开销阻止了哪些验证


总结:OpenClaw Test Heap Leaks 是 OpenClaw 项目中用于诊断和修复测试内存泄漏的专业技能。它通过堆快照对比、RSS 趋势分析和专用运行时验证工具,帮助区分“真实应用对象泄漏”与“Vite/Vitest 转换模块保留”两类不同性质的内存问题,并提供针对性的修复策略。该技能适用于 OpenClaw 贡献者和维护者在测试 OOM 排查、内存回归预防和运行时闭包泄漏验证的场景。