Skip to content

fix: resolve benchmark cold start OOM by resetting DFA cache - #497

Merged
Cythia828 merged 1 commit into
mainfrom
fix/benchmark-oom
Oct 30, 2026
Merged

Cythia828 merged 1 commit into
mainfrom
fix/benchmark-oom

Conversation

@liuxy0551

@liuxy0551 liuxy0551 commented Oct 27, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes #498

现象与背景

在执行 MySQL 等语法的冷启动基准测试(如 npm run benchmark 或 npm run benchmark:release)时,进程经过多轮迭代后出现堆内存溢出(JavaScript heap out of memory)。

问题根因

  1. 模块重载导致内存滞留:此前 cold benchmark 每轮通过在 clearATNCache() 中删除 require.cache 重新 require 模块以模拟无状态冷启动。但在 tsx/Node 环境下,模块重新求值会导致重复创建大型静态 ATN、反序列化结构和 DFA 数组,旧模块闭包与已求值 ES 模块在 V8 内部无法被 GC 卸载,每轮净增约 30~37MB 内存,累积突破堆上限导致 OOM。
  2. 命令参数语法错误:package.json 中的 test 与 benchmark 脚本使用了 NODE_OPTIONS=... && ... 语法,中间的 && 导致环境变量未能正确导出给后续子进程。

修复方案

  1. 基类新增重置能力 (src/parser/common/basicSQL.ts):
    • 暴露 resetDfaCache() 方法,调用 antlr4ng 的 interpreter.clearDFA() 原位清空共享决策状态,并重置实例输入与 parseTree 缓存。
  2. 重构 benchmark 缓存重置与模块复用 (benchmark/sqlBenchmark.ts):
    • 缓存并复用已加载的 Parser 类,避免重复 require 模块;
    • 冷启动迭代及热启动预热前,统一通过 parser.resetDfaCache() 清理决策状态,100% 保持冷启动的语法测试语义。
  3. 修复启动脚本与传参 (package.json, scripts/benchmark.js):
    • 修复 package.json 中的 NODE_OPTIONS 语法错误,确保内存参数生效;
    • 在 scripts/benchmark.js 中补充 --hot 传参与默认内存上限继承。
  4. 单元测试 (test/common/basicSQL.test.ts):
    • 增加 resetDfaCache 针对共享 DFA 状态生成、重置与后续再次解析正确性的回归测试。

验证

  • 运行 pnpm benchmark --lang=mysql 跑完全部 12 组用例 × 5 轮(共 60 轮冷启动),内存稳定在 120MB~260MB 区间,彻底解决 OOM 问题;
  • 运行 pnpm benchmark --lang=mysql --hot 验证热启动,首轮后均稳定在毫秒级;
  • pnpm test 全量单元测试(224 个套件,6524 个测试)全部通过;
  • pnpm check-types 类型检查通过。

@liuxy0551 liuxy0551 self-assigned this Oct 27, 2026
@liuxy0551
liuxy0551 requested a review from Cythia828 October 27, 2026 05:46
@Cythia828
Cythia828 merged commit 2e0f296 into main Oct 30, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: MySQL benchmark 冷启动内存泄漏导致 OOM

2 participants