我不会依赖步骤数或任何调试作为测试
要么回溯,要么失败。
一般来说,远离简单的构造,例如(A+)*,这不仅
回溯内部A+,但也回溯外部(..)*。
outter 的每一遍都会产生一个新的(新的)inner 系列的回溯。
获得像RegexFormat这样好的基准测试软件
并测试一个系列的指数时间结果。
随着内容的增加,您正在寻找线性结果
数量。
下面是(A+)? 与(A+)* 的示例。我们将目标设置为已知故障
并稳步增加长度以扩展该故障的处理。
如果您查看正则表达式 2 (A+)*,您会注意到只是指数增长
三个目标增加。
最后,我们爆出目标,使引擎内部资源过载。
编辑:经过一些分析,我对回溯步骤发表了一个微不足道的结论。
通过分析下面的基准时间,回溯似乎是一个 2^N 过程。
其中 N 是失败时回溯的字符文字数。
鉴于 Revo 的简单案例,隔离回溯会更容易一些。
因为看起来总时间的 %98 只涉及回溯。
鉴于该假设,人们可以从 2 个点获取时间结果,并生成一个方程。
我使用的方程式的形式是f(x) = a * r^x。
给定坐标('A 的# 与所用时间),使用点
(7, 1.13) , (9, 4.43) 生成了这个f(x) = 0.009475 * 1.9799 ^ x
真的是这个# sec's = 0.009475 * 1.9799 ^ # letters
我将下面基准中的所有字母“A”的数量都放入了这个公式中。
#LTR's Bench Time
7 1.13
9 4.43
13 70.51
它产生了准确的基准时间 (+/- .1%)。
然后我看到 1.9799 非常接近 2.0,所以我将“a”因子调整为 0.009 并再次运行它,得到:
f(7 letters) = 2 ^ 7 * .009 = 1.152 sec’s
f(9 letters) = 2 ^ 9 * .009 = 4.608 sec’s
f(13 letters) = 2 ^ 13 * .009 = 73.728 sec’s
f(27 letters) = 2 ^ 27 * .009 = 1207959.552 sec’s = 335 hours
现在似乎很清楚,回溯步骤与次数相关
在 2 ^ N 关系中回溯的字母。
我还认为,一些引擎可以做这个简单的 2^N 数学运算是公平的赌注
仅在像这样的简单场景中。这些似乎是时代
引擎立即返回并说太复杂了!。
这里的翻译是正则表达式足够简单,引擎可以
检测它。其他时候,引擎永远不会回来,
它挂了,可能会在一两年(或十年……)内回来。
因此,结论不是引擎是否会回溯,它会,而是如何
你的目标字符串会影响回溯吗?
所以,写正则表达式需要警惕,一定要提防
嵌套的开放式量词。
我想说,最好的办法总是打一个正则表达式 真正困难 让它失败。
而且我说的是可疑地方的过多重复文字。
结束编辑
Benchmark App
目标:AAAAAAAC
基准测试
Regex1: ^(A+)?B
Options: < none >
Completed iterations: 50 / 50 ( x 1000 )
Matches found per iteration: 0
Elapsed Time: 0.07 s, 72.04 ms, 72040 µs
Regex2: ^(A+)*B
Options: < none >
Completed iterations: 50 / 50 ( x 1000 )
Matches found per iteration: 0
Elapsed Time: 1.13 s, 1126.44 ms, 1126444 µs
目标:AAAAAAAAAC
基准测试
Regex1: ^(A+)?B
Options: < none >
Completed iterations: 50 / 50 ( x 1000 )
Matches found per iteration: 0
Elapsed Time: 0.08 s, 82.43 ms, 82426 µs
Regex2: ^(A+)*B
Options: < none >
Completed iterations: 50 / 50 ( x 1000 )
Matches found per iteration: 0
Elapsed Time: 4.43 s, 4433.19 ms, 4433188 µs
目标:AAAAAAAAAAAAAC
基准测试
Regex1: ^(A+)?B
Options: < none >
Completed iterations: 50 / 50 ( x 1000 )
Matches found per iteration: 0
Elapsed Time: 0.10 s, 104.02 ms, 104023 µs
Regex2: ^(A+)*B
Options: < none >
Completed iterations: 50 / 50 ( x 1000 )
Matches found per iteration: 0
Elapsed Time: 70.51 s, 70509.32 ms, 70509321 µs
目标:AAAAAAAAAAAAAAAAAAAAAAAAAAAAC
基准测试
Regex1: ^(A+)?B
Options: < none >
Completed iterations: 50 / 50 ( x 1000 )
Matches found per iteration: 0
Elapsed Time: 0.18 s, 184.05 ms, 184047 µs
Regex2: ^(A+)*B
Options: < none >
Error: Regex Runtime Error !!
Completed iterations: 0 / 50 ( x 1000 )
Matches found per iteration: -1
Elapsed Time: 0.01 s, 7.38 ms, 7384 µs
Error item 2 : Target Operation ..
The complexity of matching the regular expression exceeded predefined
bounds. Try refactoring the regular expression to make each choice made by
the state machine unambiguous. This exception is thrown to prevent
"eternal" matches that take an indefinite period time to locate.