mcpField
O
openclaw-test-heap-leaks

openclaw-test-heap-leaks

github.com/openclaw测试与质量393.3k642 次安装今天更新
代码仓库

关于 openclaw-test-heap-leaks

用于诊断 Vitest 测试中的内存增长,并验证运行时泄漏修复的技能。它结合性能分析、堆证据和定向验证,区分模块图保留与应用对象泄漏。

主要功能

  1. 01按原测试配置复现内存增长
  2. 02收集 CPU、堆分析与快照证据
  3. 03区分模块保留和运行时泄漏
  4. 04按进程比较堆快照
  5. 05用专用测试工具验证运行时修复

适用场景

  1. 01调查 Vitest 工作进程内存上升
  2. 02通过堆快照追踪保留对象
  3. 03检查闭包泄漏修复
  4. 04选择测试路由或清理路径调整

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/openclaw/openclaw --skill openclaw-test-heap-leaks

安装后在 Claude Code 中输入/openclaw-test-heap-leaks确认已加载。

附带文件agents/openai.yamlscripts/heapsnapshot-delta.mjs

详细介绍

OpenClaw 测试堆内存泄漏

将此技能用于测试内存调查。如果有堆快照,不要仅凭 RSS 猜测。将快照名称的差异视为初步排查证据,而非结论;只有保留者或支配对象分析支持判断后,才能下结论。

先阅读 ../openclaw-test-performance/SKILL.md,了解当前的测试性能命令和证据判定方式。

对于运行时修复(例如网关等长期运行的服务中的闭包泄漏),请参阅下方的验证运行时修复——该方法使用专用测试框架,而非单元测试性能分析工作流。

工作流

  1. 首先复现出现问题的场景。

    • 匹配实际入口和工作进程预算。要获取涵盖范围较广的 unit-fast 基线,以及每种配置的最大 RSS 和耗时最高的文件,请从以下命令开始:

      pnpm test:perf:groups \
        --config test/vitest/vitest.unit-fast.config.ts \
        --allow-failures \
        --output .artifacts/test-perf/unit-fast-memory.json
      
    • 对于怀疑有问题的文件,使用一个工作进程重新运行该文件,并收集耗时和 RSS 证据:/usr/bin/time -l pnpm test <file> --maxWorkers=1 --reporter=verbose。

    • 当前的 pnpm test 执行计划由 scripts/test-projects.mts 制定。记录打印出的 Vitest 配置或分片,并在报告特定于配置或工作进程预算时保留该运行形态。

  2. 收集最有力的堆内存证据。

    • 运行 pnpm test:perf:profile:runner -- --output-dir .artifacts/test-perf/vitest-runner-profile -- <file>,为单元测试运行器生成 CPU 性能分析和采样堆性能分析。在 DevTools 中打开堆性能分析文件,并检查占用最大的分配类型。
    • 采样生成的 .heapprofile 不是 .heapsnapshot;不要将其传给快照差异辅助脚本。
    • 如果专用测试框架或其他已知生成器会输出多个 .heapsnapshot 文件,请使用 .agents/skills/openclaw-test-heap-leaks/scripts/heapsnapshot-delta.mjs 比较同一 PID 的快照。
    • 如果没有可用的快照或堆性能分析文件,RSS 增长可作为初步排查证据,但泄漏分类仍应保持为未定。
  3. 先对增长进行分类,再选择修复方案。

    • 如果增长主要来自 Vite/Vitest 转换后的源码字符串、Module、system / Context、字节码、描述符数组或属性映射,则将其视为长期运行的工作进程中模块图可能被保留而持续增长。
    • 如果增长主要来自应用对象、缓存、缓冲区、服务句柄、计时器、模拟状态、sqlite 状态或类似运行时对象,则将其视为可能存在清理或生命周期泄漏。
    • 如果名称含义不明确,不要轻率下结论;请在 DevTools 中检查主要差异项的保留者或支配对象。
  4. 修复正确的层面。

    • 对于共享工作进程中可能由保留转换后模块导致的增长:
    • 检查所属的 Vitest 配置和 scripts/test-projects.test-support.mjs 中的进程分块。只有在相同运行形态的证据表明原因是共享工作进程保留模块时,才在此处调整进程生命周期或项目归属。
    • test/vitest/vitest.unit-fast-isolated.config.ts 用于经审查、需要全新模块图的有状态测试。不要将其用作通用的内存热点列表。
    • 对于实际泄漏:
    • 修复涉及的测试或运行时清理路径。
    • 检查是否缺少 afterEach/afterAll、模块重置不完整、全局状态被保留、DB 句柄未释放,或监听器/计时器在文件运行结束后仍然存在。
  5. 使用最直接的证据进行验证。

    • 重新运行相同的分组或限定范围命令,确认最大 RSS 趋势或 OOM 已改善。
    • 如果专用生成器会输出堆性能分析文件或快照,请重复运行同一生成器并比较等效产物。
    • 对于路由或配置变更,验证预期的 Vitest 配置或分片已启动,且受影响的测试已完成。

启发式判断

  • 不要把所有情况都称为泄漏。在非隔离的共享 Vitest 项目中,增长可能是 worker 生命周期问题,而不是应用对象泄漏。
  • scripts/test-projects.mts、scripts/test-group-report.mts 和 scripts/run-vitest-profile.mts 分别是当前的执行、分组 RSS 和性能分析入口。
  • [test] starting ... 行用于确定要复现的 Vitest 配置或分片。
  • .artifacts/vitest-shard-timings.json 存储用于调度的配置/分片耗时。它不是文件级内存热点或行为清单。
  • 如果同一 worker PID 中的相同保留对象类型在多个时间间隔内持续增长,应以快照为准,而不是凭直觉判断;然后通过保留者证据确认有疑问的调用。

快照对比

  • 直接对比:
    • node .agents/skills/openclaw-test-heap-leaks/scripts/heapsnapshot-delta.mjs before.heapsnapshot after.heapsnapshot
  • 在单个 lane 中按 PID 自动选择最早和最晚的快照:
    • node .agents/skills/openclaw-test-heap-leaks/scripts/heapsnapshot-delta.mjs --lane-dir <snapshot-directory>
  • 常用标志:
    • --top 40
    • --min-kb 32
    • --pid 16133

先查看增幅最大的正向差值。模块转换产物大幅增长,说明问题可能与共享进程生命周期或项目所有权有关;运行时对象大幅增长,则可能是真正的泄漏。如果仅凭名称无法确定原因,请先在 DevTools 中打开同一组快照,并检查排名靠前条目的保留者/支配者,再判定根因。

验证运行时修复(非测试内存)

上述工作流用于诊断 Vitest worker 内存增长。若要验证运行时/闭包修复确实释放了捕获的状态,请使用专用测试工具:

  • pnpm leak:embedded-run — 运行 scripts/embedded-run-abort-leak.ts。在模拟 runEmbeddedAttempt 的函数作用域中循环执行 N 次中止的运行,写入堆快照,并使用 FinalizationRegistry 跟踪实例计数,同时结合 RSS 差值,报告保留增长的 PASS/FAIL 结论。

模式:

  • closure-extracted(默认)— 生产修复形态(辅助函数位于模块作用域)。
  • closure-inline — 修复前的形态(闭包位于 runner 作用域内)。将其用作灵敏度检查:如果它通过,说明你破坏了测试工具,而不是修复了 bug。
  • synthetic-leak — 通过模块级 bucket 故意保留对象。先用它确认测试工具能检测到泄漏,再相信真实修复的 PASS 结果。

快照保存在 .tmp/embedded-run-abort-leak/ 中。使用与上述相同的脚本进行差异对比:

node .agents/skills/openclaw-test-heap-leaks/scripts/heapsnapshot-delta.mjs \
  .tmp/embedded-run-abort-leak/baseline-*.heapsnapshot \
  .tmp/embedded-run-abort-leak/batch-N-*.heapsnapshot --top 30

修复其他运行时泄漏时,应在此测试工具旁添加新的测试工具,而不是改造现有工具。测试夹具函数应模拟发生泄漏的函数的词法作用域,而不是使用通用的中止循环。

输出要求

使用此技能时,请报告:

  • 精确的复现命令。
  • 复现了哪个 Vitest 配置或目标,以及有快照时对比了哪个 PID。
  • 堆分析或快照差值中占主导地位的保留对象类型(如有)。
  • 问题更可能是真正的泄漏,还是共享 worker 中保留的模块增长,以及保留者/支配者检查是否证实了这一判断。
  • 具体的修复或降低影响的补丁。
  • 你验证了哪些内容,以及哪些内容因快照开销而无法验证。

评论

支持 Markdown