摘要:最近用到做一些文本處理,免不了涉及正則表達(dá)式,由于文本的規(guī)模會(huì)達(dá)到級(jí),速度和還是很關(guān)鍵的。根據(jù)上的測(cè)試發(fā)現(xiàn),如果需要用到正則去匹配的話,還是預(yù)編譯的表達(dá)式表現(xiàn)最好??窗l(fā)現(xiàn)有一個(gè)代表也就是嘗試所有可能的匹配。上的相關(guān)解釋如下。
最近用到j(luò)s做一些文本處理,免不了涉及正則表達(dá)式,由于文本的規(guī)模會(huì)達(dá)到GB級(jí),速度和還是很關(guān)鍵的。
根據(jù) jsperf 上的測(cè)試發(fā)現(xiàn),如果需要用到正則去匹配的話,還是預(yù)編譯的表達(dá)式precompiled search表現(xiàn)最好。這是一個(gè)比較容易也比較重要的優(yōu)化項(xiàng)。
看MDN發(fā)現(xiàn)有一個(gè)g flag代表global match也就是嘗試所有可能的匹配。MDN上的相關(guān)解釋如下。
Whether to test the regular expression against all possible matches in a string, or only against the first.
所有的又產(chǎn)生了一個(gè)疑問(wèn),如果我這需要判斷是否存在一個(gè)表達(dá)式,不需要知道幾個(gè),也就是只用RegExp.test(),需不需要g flag,感覺(jué)加上有可能會(huì)使速度變慢,但是不確定,寫(xiě)了一個(gè)很簡(jiǎn)陋的性能測(cè)試。
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);
分別去掉注釋分別運(yùn)行發(fā)現(xiàn)帶g flag的需要25-30ms,而不帶g flag的卻需要40+ms,和直覺(jué)相反。然后回想了一下g flag的作用,接著看文檔,發(fā)現(xiàn)一個(gè)叫做lastIndex的屬性:
The lastIndex is a read/write integer property of regular expressions that specifies the index at which to start the next match.
得知既然是嘗試匹配所有可能,如果沒(méi)有主動(dòng)把lastIndex清零,則會(huì)繼續(xù)上一次的匹配知道結(jié)束。所以以上代碼如果是帶g flag的情況上一次匹配完成,已經(jīng)到了句末,加入此時(shí)console.log(globalRegex.lastIndex)會(huì)得到testStr.length,而且下一次會(huì)繼續(xù)嘗試向后匹配,并另計(jì)返回false。所以可以理解上述的時(shí)間差。
假如把for循環(huán)中帶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); }
兩種情況的運(yùn)行結(jié)果都在40+ms。
結(jié)論:即使加上g flag理論上也不影響速度,只需要將lastIndex清零,不過(guò)清零還是需要消耗的,所以如果只需要匹配判斷,可以不用g flag
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/85350.html
摘要:是一個(gè)極度純凈的上傳插件,通過(guò)簡(jiǎn)單調(diào)整就可以融入到任何項(xiàng)目,支持多文件上傳上傳速率動(dòng)態(tài)控制真實(shí)進(jìn)度監(jiān)控分塊生成分塊上傳校驗(yàn)秒傳暫停取消等。 跨域?qū)W習(xí)筆記 前言: 當(dāng)一個(gè)資源,向與之所在服務(wù)器不同的域或端口請(qǐng)求另一個(gè)資源時(shí),這個(gè)HTTP請(qǐng)求,我們認(rèn)為是跨域的請(qǐng)求。出于安全考慮,瀏覽器會(huì)限制腳本發(fā)起的跨域HTTP請(qǐng)求。 那天后端讓我把token放到http請(qǐng)求頭字段里,說(shuō)是為了和RN端統(tǒng)一...
摘要:性能訪問(wèn)字面量和局部變量的速度是最快的,訪問(wèn)數(shù)組和對(duì)象成員相對(duì)較慢變量標(biāo)識(shí)符解析過(guò)程搜索執(zhí)行環(huán)境的作用域鏈,查找同名標(biāo)識(shí)符。建議將全局變量存儲(chǔ)到局部變量,加快讀寫(xiě)速度。優(yōu)化建議將常用的跨作用域變量存儲(chǔ)到局部變量,然后直接訪問(wèn)局部變量。 缺陷 這本書(shū)是2010年出版的,這本書(shū)談性能是有時(shí)效性的,現(xiàn)在馬上就2018年了,這幾年前端發(fā)展的速度是飛快的,書(shū)里面還有一些內(nèi)容考慮IE6、7、8的東...
摘要:當(dāng)執(zhí)行上下文被創(chuàng)建時(shí),它的作用域鏈初始化為當(dāng)前運(yùn)行函數(shù)的屬性中的對(duì)象。該過(guò)程搜索執(zhí)行環(huán)境的作用域鏈,查找同名的標(biāo)識(shí)符。搜索實(shí)例成員比從字面量或局部變量中讀取數(shù)據(jù)代價(jià)更高,再加上遍歷原型鏈帶來(lái)的開(kāi)銷(xiāo),這讓性能問(wèn)題更為嚴(yán)重。 最近在閱讀這本Nicholas C.Zakas(javascript高級(jí)程序設(shè)計(jì)作者)寫(xiě)的最佳實(shí)踐、性能優(yōu)化類的書(shū)。記錄下主要知識(shí)。 加載和執(zhí)行 腳本位置 放在中的...
摘要:當(dāng)執(zhí)行上下文被創(chuàng)建時(shí),它的作用域鏈初始化為當(dāng)前運(yùn)行函數(shù)的屬性中的對(duì)象。該過(guò)程搜索執(zhí)行環(huán)境的作用域鏈,查找同名的標(biāo)識(shí)符。搜索實(shí)例成員比從字面量或局部變量中讀取數(shù)據(jù)代價(jià)更高,再加上遍歷原型鏈帶來(lái)的開(kāi)銷(xiāo),這讓性能問(wèn)題更為嚴(yán)重。 最近在閱讀這本Nicholas C.Zakas(javascript高級(jí)程序設(shè)計(jì)作者)寫(xiě)的最佳實(shí)踐、性能優(yōu)化類的書(shū)。記錄下主要知識(shí)。 加載和執(zhí)行 腳本位置 放在中的...
閱讀 1877·2023-04-25 22:42
閱讀 2245·2021-09-22 15:16
閱讀 3513·2021-08-30 09:44
閱讀 511·2019-08-29 16:44
閱讀 3340·2019-08-29 16:20
閱讀 2539·2019-08-29 16:12
閱讀 3410·2019-08-29 16:07
閱讀 694·2019-08-29 15:08