近来用到js做一些文本处理,免不了触及正则表达式,因为文本的范围会到达GB级,速率和照样很症结的。
依据 jsperf 上的测试发明,如果须要用到正则去婚配的话,照样预编译的表达式precompiled search
表现最好。这是一个比较轻易也比较主要的优化项。
看MDN发明有一个g flag
代表global match也就是尝试一切能够的婚配。MDN上的相干诠释以下。
Whether to test the regular expression against all possible matches in a string, or only against the first.
一切的又产生了一个疑问,如果我这须要推断是不是存在一个表达式,不须要晓得几个,也就是只用RegExp.test()
,需不须要g flag
,觉得加上有能够会使速率变慢,然则不确定,写了一个很大略的机能测试。
var start = +new Date(),
end,
globalRegex = /someone/g,
nonGlobalRegex = /someone/,
testStr = 'This optimization makes the lexer more than twice as fast! Why does this make sense? First, if you think about it in the simplest way possible, the iteration over rules moved from Python code to C code (the implementation of the re module). Second, its even more than that. In the regex engine, | alternation doesnt simply mean iteration. When the regex is built, all the sub-regexes get combined into a single NFA - some states may be combined, etc. In short, the speedup is not surprising.someone';
for (var i = 100000; i >= 0; i--) {
// with a g flag
globalRegex.test(testStr);
// without g flay
// nonGlobalRegex.test(testStr);
}
end = +new Date();
console.log(end - start);
离别去掉解释离别运转发明带g flag
的须要25-30ms,而不带g flag
的却须要40+ms,和直觉相反。然后回想了一下g flag
的作用,接着看文档,发明一个叫做lastIndex
的属性:
The lastIndex is a read/write integer property of regular expressions that specifies the index at which to start the next match.
得知既然是尝试婚配一切能够,如果没有主动把lastIndex
清零,则会继承上一次的婚配晓得完毕。所以以上代码如果是带g flag
的状况上一次婚配完成,已到了句末,到场此时console.log(globalRegex.lastIndex)
会获得testStr.length
,而且下一次会继承尝试向后婚配,并另计返回false。所以能够明白上述的时间差。
如果把for循环中带g flag
的状况加一句:
for (var i = 100000; i >= 0; i--) {
// with a g flag
globalRegex.test(testStr);
globalRegex.lastIndex = 0;
// without g flay
// nonGlobalRegex.test(testStr);
}
两种状况的运转效果都在40+ms。
结论:纵然加上g flag
理论上也不影响速率,只须要将lastIndex
清零,不过清零照样须要斲丧的,所以如果只须要婚配推断,能够不必g flag