一次簡單的js正則表達式的性能測試

最近用到js作一些文本處理,免不了涉及正則表達式,因爲文本的規模會達到GB級,速度和仍是很關鍵的。正則表達式

根據 jsperf 上的測試發現,若是須要用到正則去匹配的話,仍是預編譯的表達式precompiled search表現最好。這是一個比較容易也比較重要的優化項。express

看MDN發現有一個g flag表明global match也就是嘗試全部可能的匹配。MDN上的相關解釋以下。jsp

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.ui

得知既然是嘗試匹配全部可能,若是沒有主動把lastIndex清零,則會繼續上一次的匹配知道結束。因此以上代碼若是是帶g flag的狀況上一次匹配完成,已經到了句末,加入此時console.log(globalRegex.lastIndex)會獲得testStr.length,並且下一次會繼續嘗試向後匹配,並另計返回false。因此能夠理解上述的時間差。this

假如把for循環中帶g flag的狀況加一句:code

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。regexp

結論:即便加上g flag理論上也不影響速度,只須要將lastIndex清零,不過清零仍是須要消耗的,因此若是隻須要匹配判斷,能夠不用g flag

相關文章
相關標籤/搜索