资讯专栏INFORMATION COLUMN

一次简单的js正则表达式的性能测试

Eric / 753人阅读

摘要:最近用到做一些文本处理,免不了涉及正则表达式,由于文本的规模会达到级,速度和还是很关键的。根据上的测试发现,如果需要用到正则去匹配的话,还是预编译的表达式表现最好。看发现有一个代表也就是尝试所有可能的匹配。上的相关解释如下。

最近用到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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/85350.html

相关文章

  • API

    摘要:是一个极度纯净的上传插件,通过简单调整就可以融入到任何项目,支持多文件上传上传速率动态控制真实进度监控分块生成分块上传校验秒传暂停取消等。 跨域学习笔记 前言: 当一个资源,向与之所在服务器不同的域或端口请求另一个资源时,这个HTTP请求,我们认为是跨域的请求。出于安全考虑,浏览器会限制脚本发起的跨域HTTP请求。 那天后端让我把token放到http请求头字段里,说是为了和RN端统一...

    lsxiao 评论0 收藏0
  • 【读书笔记】《高性能JavaScript》

    摘要:性能访问字面量和局部变量的速度是最快的,访问数组和对象成员相对较慢变量标识符解析过程搜索执行环境的作用域链,查找同名标识符。建议将全局变量存储到局部变量,加快读写速度。优化建议将常用的跨作用域变量存储到局部变量,然后直接访问局部变量。 缺陷 这本书是2010年出版的,这本书谈性能是有时效性的,现在马上就2018年了,这几年前端发展的速度是飞快的,书里面还有一些内容考虑IE6、7、8的东...

    chengjianhua 评论0 收藏0
  • 《高性能javascript》阅读摘要

    摘要:当执行上下文被创建时,它的作用域链初始化为当前运行函数的属性中的对象。该过程搜索执行环境的作用域链,查找同名的标识符。搜索实例成员比从字面量或局部变量中读取数据代价更高,再加上遍历原型链带来的开销,这让性能问题更为严重。 最近在阅读这本Nicholas C.Zakas(javascript高级程序设计作者)写的最佳实践、性能优化类的书。记录下主要知识。 加载和执行 脚本位置 放在中的...

    duan199226 评论0 收藏0
  • 《高性能javascript》阅读摘要

    摘要:当执行上下文被创建时,它的作用域链初始化为当前运行函数的属性中的对象。该过程搜索执行环境的作用域链,查找同名的标识符。搜索实例成员比从字面量或局部变量中读取数据代价更高,再加上遍历原型链带来的开销,这让性能问题更为严重。 最近在阅读这本Nicholas C.Zakas(javascript高级程序设计作者)写的最佳实践、性能优化类的书。记录下主要知识。 加载和执行 脚本位置 放在中的...

    afishhhhh 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<