2007-05-30
javascript 性能测试系列:正则表达式
在JSI的实现中,有这样一种需求,将有自带命名空间的脚本元素名数组转换成没有命名空间的变量名数组.
比如 :
['YAHOO.util.XXXX,YAHOO.util.YYYY,YAHOO.event.XX'] ->['YAHOO']
以前一直是较长的一段处理代码,今天突发奇想,这个用正则表达式处理效果如何?
于是,就这种处理,分别测试了正则表达式和javascript代码的效率.
测试数据如下(regTime /codeTime):
620/4536
729/4068
719/4250
645/4152
655/4642
FF和IE结果差不多,上面是FF2的数据
总结:
经常看见很多地方对正则表达式的效率的怀疑,但是这个问题放在javascript里面,好像情况又不同了. 适当使用正则式,反而可以大大提高效率.
在javascript这类\较慢的解释型语言里面,少即快,能用原生代码就不要自己写.
测试代码:
注:
这段正则代码是不严谨的,当数组中有多个命名空间,且顺序打乱时,不能剔除全部重复变量.不过JSI中对这个结果尚可接受.
比如 :
['YAHOO.util.XXXX,YAHOO.util.YYYY,YAHOO.event.XX'] ->['YAHOO']
以前一直是较长的一段处理代码,今天突发奇想,这个用正则表达式处理效果如何?
于是,就这种处理,分别测试了正则表达式和javascript代码的效率.
测试数据如下(regTime /codeTime):
620/4536
729/4068
719/4250
645/4152
655/4642
FF和IE结果差不多,上面是FF2的数据
总结:
经常看见很多地方对正则表达式的效率的怀疑,但是这个问题放在javascript里面,好像情况又不同了. 适当使用正则式,反而可以大大提高效率.
在javascript这类\较慢的解释型语言里面,少即快,能用原生代码就不要自己写.
测试代码:
- var data = [];
- for(var i = 0;i<20;i++){
- data[i] = "NS"+i/10+'.'+i
- }
- document.write(
- //(data == data.sort()) +"/"+
- data +"<hr>")
- var i = 0;
- var regTime = 0;
- var codeTime = 0;
- var inc = 0;
- var reg = /(\b[\$\w]+)[\$\w\.]*(,\1\b[\$\w\.]*)*/g;
- var regResult,codeResult;
- while(inc++<100){
- var i=0;
- var t1 = new Date();
- while(i++<100){
- regResult = data.join(',').replace(reg,'$1').split(',');
- }
- var t2 = new Date();
- while(i++<200){
- codeResult = [];
- var flagMap = {};
- for(var j=data.length-1;j>=0;j--){
- key = data[j];
- key = key.substr(0,key.indexOf('.'));
- if(!flagMap[key]){
- codeResult[codeResult.length] = (key);
- //codeResult.push(key);
- flagMap[key] = true;
- }
- }
- }
- var t3 = new Date();
- regTime +=(t2-t1);
- codeTime+=(t3-t2);
- }
- document.write(
- "regResult:"+
- regResult)
- document.write(
- "<hr>codeResult:"+
- codeResult)
- prompt("regTime /codeTime",regTime +'/'+codeTime)
注:
这段正则代码是不严谨的,当数组中有多个命名空间,且顺序打乱时,不能剔除全部重复变量.不过JSI中对这个结果尚可接受.


评论
可以这么说吧,反正就是,记录真实变量名,而不是一个带命名空间的路径
关于Date.format,我的第一种实现是不能用来实现Date.format的,因为它依赖于$1,$2这样的形式,然后进行反向替换。
但是第二种可以用。我以后可以写一个DateFormatter。
就是将一段带有命名空间的脚本元素名数组转换成 没有命名空间的数组.
以YUI的event.js为例:
this.addScript("event.js",['YAHOO.util.CustomEvent','YAHOO.util.Subscriber','YAHOO.util.Event']);
在注册完 对象->脚本表之后,需要设置 脚本->对象表
这时,我需要将对象数组转换成['YAHOO']
确实,复杂的正则的易用性可读性都很低,所以我也只是在某些性能要求高的地方做些优化.
如果用这种方式去写个Date.format估计更受欢迎的:)
关于正则,通常有助于提高js的性能。例子如有人利用正则实现indexOf,有人用正则实现字符串map。
使用正则的特别好处(也是在使用时应时刻记住的)是,可以将多次函数调用变为一次regexp调用。多次js函数调用的开销肯定大于单次的普通regexp调用。而且有时候函数调用的次数是不定的,而regexp可以保持基本常量的性能。
这里有一个极佳例子,用正则实现String.format,比通常的正则函数查找要快,而且格式越复杂越能体现优势,具体参见:http://johnhax.blogspot.com/2006/12/string-format-function-for-javascript.html
不过正则的问题在于兼容性,老的js引擎如jscript 5.0等对正则支持不完整。另外写正则和维护正则是一件很头大的事情。