正则表达式性能基准测试工具

执行 N 次正则匹配统计平均/最大/最小/标准差耗时,静态分析检测嵌套量词、重叠分支、通配量词三类 ReDoS 危险模式, 渐进式压力测试用递增长度输入判断是否指数级回溯。内置经典 ReDoS 示例 (a+)+ 与安全正则示例。所有数据仅在浏览器本地处理。

//
1-1000(推荐 100,过大可能卡顿)
预设示例:

输入正则表达式后点击「开始基准测试」或「渐进压力测试」

或点击「载入示例」体验经典 ReDoS 模式

常见问题

什么是 ReDoS?为什么正则表达式会有安全问题?

ReDoS(Regular Expression Denial of Service,正则表达式拒绝服务)是指攻击者构造恶意输入, 使正则表达式匹配时产生指数级回溯,导致 CPU 占用 100% 甚至浏览器/服务崩溃。 根本原因是某些正则引擎(如 JavaScript 的 NFA 引擎)在匹配失败时会尝试所有可能的路径, 当正则含嵌套量词(如 (a+)+)、重叠分支(如 (a|a)*)时, 回溯路径数会随输入长度呈指数增长。例如正则 ^(a+)+$ 匹配 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa! (30 个 a 加一个 !)可能耗时数秒甚至数分钟。

哪些正则模式容易触发 ReDoS?

常见的三类危险模式:
1. 嵌套量词(a+)+(a*)*(a{2,})+([a-z]+)*, 捕获组内含量词且组外又跟量词,回溯路径数指数增长;
2. 重叠分支 + 量词(a|a)*(ab|a)*(\d|\w)*, 分支间存在重叠时,引擎会尝试所有分支组合;
3. 通配量词.+.*[^x]+, 通配符匹配范围过广,在大输入上产生大量回溯。
此外,\w+\w+\d+\d+ 等相邻重复量词也会产生回溯。

嵌套量词为什么危险?回溯是如何发生的?

(a+)+ 匹配 aaaa! 为例:
- 内层 a+ 先贪婪匹配全部 4 个 a;
- 外层 + 满足,继续匹配 $ 但遇到 ! 失败;
- 引擎回溯:内层 a+ 释放 1 个 a,匹配 3 个 a;
- 外层 + 尝试第二组 (a+),匹配剩下的 1 个 a;
- 继续匹配 $ 仍失败,继续回溯……
对于 n 个 a,回溯路径数约为 2n,n=30 时约 10 亿路径,CPU 直接卡死。 这就是 ReDoS 的本质:回溯路径数随输入长度指数增长。

基准测试的迭代次数怎么选?

迭代次数决定统计样本大小:
- 1-10 次:快速验证,结果波动大,仅用于判断正则是否能正常运行;
- 100 次(默认):推荐值,统计稳定且总耗时可控(< 2 秒);
- 500-1000 次:高精度统计,适合对比微秒级差异,但总耗时可能较长。
本工具内置超时保护:若总耗时超过 2000 ms 自动中止,避免卡死浏览器。 对于 ReDoS 正则,建议先用压力测试验证风险,再决定是否做大量迭代。

渐进压力测试如何判断指数增长?

压力测试用 5 个递增长度(10, 20, 30, 40, 50 字符)的输入分别测量执行耗时,然后比较时间增长倍数与长度增长倍数:
- 若 时间增长倍数 > 长度增长倍数 × 5,且最长耗时 > 10 ms,判定为指数增长(高风险);
- 若单次耗时超过 1000 ms 自动中止,标记为已超时(高风险);
- 否则判定为线性增长(相对安全)。
例如长度 10 耗时 0.1 ms,长度 50 耗时 100 ms,时间增长 1000 倍而长度增长 5 倍,1000 > 5×5=25,判定为指数增长。 注意:压力测试用测试字符串的第一个字符作为基础字符重复填充,建议载入「经典 ReDoS」示例体验。

与正则表达式测试工具有何区别?

正则表达式测试工具关注功能正确性:实时高亮匹配、显示捕获组、支持替换, 适合验证正则是否匹配预期内容。
本工具关注性能与安全:测量执行耗时、检测 ReDoS 风险、判断回溯是否指数增长, 适合上线前对正则做性能审计。
两者互补:先用测试工具验证功能,再用本工具验证性能。本工具的静态分析可在输入正则后实时显示风险等级, 无需点击按钮;基准测试与压力测试需手动触发。

数据会上传到服务器吗?

不会。本工具完全在浏览器内运行,所有正则编译、匹配、计时逻辑由 JavaScript 在你本地执行,输入内容不会发送到任何服务器。性能基准基于浏览器原生的 performance.now() 高精度计时器,测量结果可能因设备性能不同而略有差异。

如何优化 ReDoS 风险正则?

优化策略(按优先级):
1. 消除嵌套量词:用原子组 (?>...) 或占有量词 a++ 限制回溯(JavaScript 不支持时改写为等价线性模式,如 (a+)+a+);
2. 消除分支重叠:确保交替分支互斥,如 (a|ab) 改为 (ab|a)(长分支在前)或提取公共前缀;
3. 用具体字符集替代通配符:如用 [^"\r\n]+ 替代 .+ 匹配带引号字符串;
4. 合并相邻量词\w+\w+\w+
5. 对超时敏感场景使用专门库:如 Node.js 的 re2 模块(基于 Google RE2,线性时间,不支持回溯);
6. 设置超时:服务端正则匹配应设置超时保护,避免单个请求拖垮服务。

为什么我的正则被标记为「高风险」但实际运行很快?

静态分析是保守判定:只要检测到危险结构(如嵌套量词)就标记为高风险, 但实际是否触发 ReDoS 取决于输入。例如 (a+)+ 匹配 aaa(纯 a)很快, 匹配 aaa!(结尾非 a)才会指数回溯。
建议结合压力测试验证:若压力测试显示线性增长,说明实际输入不会触发回溯; 若显示指数增长或超时,说明确实存在 ReDoS 风险,需优化。
静态分析的价值在于提前预警:即使当前输入不触发,未来输入变化时可能触发。