JavaScript 解析Json字符串的性能比较分析代码


Posted in Javascript onDecember 16, 2009

解析时用到的方法一般是eval或者new function,而目前IE8和Firefox3.1又内置了原生的JSON对象(据说会有一定的性能提升)。那我们在实际使用的时候怎样从这三种方法(因为性能问题,不考虑用javascript实现的解析)里面来选择呢?面对众多的浏览器,哪种方式的性能是最好的呢?

一、测试方法

1、首先指定测试次数及JSON字符串

var count = 10000, o = null, i = 0, jsonString = '{"value":{"items": [{"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}]},"error":null}';

2、循环解析并记录时间

eval

var beginTime = new Date(); 
for ( i = 0; i < count; i++ ) { 
o = eval( "(" + jsonString + ")" ); 
} 
Console.output( "eval:" + ( new Date() - beginTime ) );

new Function
var beginTime = new Date(); 
for ( i = 0; i < count; i++ ) { 
o = new Function( "return " + jsonString )(); 
} 
Console.output( "new Function:" + ( new Date() - beginTime ) );

native
if ( typeof JSON !== "undefined" ) { 
var beginTime = new Date(); 
for ( i = 0; i < count; i++ ) { 
o = JSON.parse( jsonString ); } 
Console.output( "native:" + ( new Date() - beginTime ) ); 
} else { 
Console.output( "native:not support!" ); 
}

二、测试对象

选择目前主流的浏览器(不考虑Maxthon一类的外壳),包括IE6、7、8,Firefox2、3、3.1,Chrome,Opera及Safari3、4。

三、测试环境

T9300 CPU + 4G RAM + Windows2003,其中IE8使用的是Vista的环境,IE7在另外一台工作机(2G CPU + 2G RAM + Windows2003),考虑到主要是测试浏览器客户端的性能,结果的误差应该能够接受。

四、测试结果
JavaScript 解析Json字符串的性能比较分析代码 
*数值越小越好

*在当前列中绿色背景的表示性能最好,红色性能最差
1、Firefox2、3全部垫底,IE6的性能优于IE7(可能和机器不一致有关),Chrome和Safari4的性能远远超出其它浏览器。

2、不同的浏览器下eval和new Function的性能不一致,总的来说eval更好,但Firefox下new Function的性能是eval的一倍,为了更好的兼容各个浏览器,我们把对JSON的解析单独封装成一个对象来处理:
wrapper

var __json = null; 
if ( typeof JSON !== "undefined" ) { 
__json = JSON; 
} 
var browser = Browser; 
var JSON = { 
parse: function( text ) { 
if ( __json !== null ) { 
return __json.parse( text ); 
} 
if ( browser.gecko ) { 
return new Function( "return " + text )(); 
} 
return eval( "(" + text + ")" ) 
} 
}; 
var beginTime = new Date(); 
for ( i = 0; i < count; i++ ) { 
o = JSON.parse( jsonString ); } 
Console.output( "wrapper:" + ( new Date() - beginTime ) );

加入Wrapper后的结果:
JavaScript 解析Json字符串的性能比较分析代码 
由于涉及到调用对象的开销,封装后JSON对象会比单独调用更慢,但它能保证在各个浏览器下使用最适合的方法。

五、结论

解析Json字符串时,不同的浏览器选择不同的方法:

IE6、7使用eval
IE8使用原生的JSON对象
Firefox2、3使用new Function
Safari4使用eval
其它浏览器下eval和new Function的性能基本一致

如果有不同意见欢迎拍砖:)

Update:

2009.03.23:屏蔽所有Firefox的Add-Ons再进行测试
由于Known在Firefox下运行代码得到了完全不一致的结果,怀疑是Firefox的插件导致,于是禁掉所有插件后(后来表明几乎由Firebug导致),重新在Firefox2、3下测试了一下,结果如下:
JavaScript 解析Json字符串的性能比较分析代码 
这表明Firefox本身的性能并不是象我们先前测试的那样低,在去掉插件后性能还是很不错。但是没有Firebug一类的插件支持,Firefox对我们的吸引力也大大降低了。

2009.03.31:循环中每次使用新的json字符串
根据Oliver的描述,他猜测是由于Safari4和Chrome缓存了eval的结果从而导致它们的测试成绩“虚”高,测试结果证明了他的推测:
JavaScript 解析Json字符串的性能比较分析代码 
从这个结果中我们可以看到,Opera的性能最好,Ie8其次。

主要修改的代码:

//eval 2: var beginTime = new Date(); 
for ( i = 0; i < count; i++ ) { 
o = eval("(" + '{"value":{"items": [{"x":' + i + ',"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}]},"error":null}' + ")"); 
} 
Console.output( "eval:" + ( new Date() - beginTime ) ); 
//new Function 
beginTime = new Date(); 
for ( i = 0; i < count; i++ ) { 
o = new Function("return " + '{"value":{"items": [{"x":' + i + ',"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}]},"error":null}')(); 
} 
Console.output( "new Function:" + ( new Date() - beginTime ) ); 
//native 
if ( typeof JSON !== "undefined" ) { 
beginTime = new Date(); 
for ( i = 0; i < count; i++ ) { 
o = JSON.parse('{"value":{"items": [{"x":' + i + ',"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}]},"error":null}'); 
} 
Console.output( "native:" + ( new Date() - beginTime ) ); 
} else { 
Console.output( "native:not support!" ); 
} 
//wrapper 
var __json = null; 
if ( typeof JSON !== "undefined" ) { 
__json = JSON; 
} 
var browser = Browser; 
var JSON = { 
parse: function( text ) { 
if ( __json !== null ) { 
return __json.parse( text ); 
} 
if ( browser.gecko ) { 
return new Function( "return " + text )(); 
} 
return eval( "(" + text + ")" ) 
} 
}; 
beginTime = new Date(); 
for ( i = 0; i < count; i++ ) { 
o = JSON.parse('{"value":{"items": [{"x":' + i + ',"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}]},"error":null}'); 
} 
Console.output( "wrapper:" + ( new Date() - beginTime ) );

附:全部代码
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> 
<html> 
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
<title>Parse JsonString</title> 
</head> 
<body> 
<div id="consoleRegion"></div> 
<script type="text/javascript"> 
//yui 
var Browser = function() { 
var o = { 
ie: 0, 
opera: 0, 
gecko: 0, 
webkit: 0 
}; 
var ua = navigator.userAgent, m; 
if ( ( /KHTML/ ).test( ua ) ) { 
o.webkit = 1; 
} 
// Modern WebKit browsers are at least X-Grade 
m = ua.match(/AppleWebKit\/([^\s]*)/); 
if (m&&m[1]) { 
o.webkit=parseFloat(m[1]); 
} 
if (!o.webkit) { // not webkit 
// @todo check Opera/8.01 (J2ME/MIDP; Opera Mini/2.0.4509/1316; fi; U; ssr) 
m=ua.match(/Opera[\s\/]([^\s]*)/); 
if (m&&m[1]) { 
o.opera=parseFloat(m[1]); 
} else { // not opera or webkit 
m=ua.match(/MSIE\s([^;]*)/); 
if (m&&m[1]) { 
o.ie=parseFloat(m[1]); 
} else { // not opera, webkit, or ie 
m=ua.match(/Gecko\/([^\s]*)/); 
if (m) { 
o.gecko=1; // Gecko detected, look for revision 
m=ua.match(/rv:([^\s\)]*)/); 
if (m&&m[1]) { 
o.gecko=parseFloat(m[1]); 
} 
} 
} 
} 
} 
return o; 
}(); 
var Console = { 
consoleRegion: null, 
getRegion: function() { 
if ( this.consoleRegion === null ) { 
this.consoleRegion = document.getElementById( "consoleRegion" ); 
} 
return this.consoleRegion; 
}, 
output: function( text ) { 
this.getRegion().innerHTML += "<br/>" + text; 
} 
}; 
//test code 
var count = 10000, o = null, i = 0, jsonString = '{"value":{"items": [{"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}]},"error":null}'; 
//eval 
var beginTime = new Date(); 
for ( i = 0; i < count; i++ ) { 
o = eval( "(" + jsonString + ")" ); 
} 
Console.output( "eval:" + ( new Date() - beginTime ) ); 
//new Function 
beginTime = new Date(); 
for ( i = 0; i < count; i++ ) { 
o = new Function( "return " + jsonString )(); 
} 
Console.output( "new Function:" + ( new Date() - beginTime ) ); 
//native 
if ( typeof JSON !== "undefined" ) { 
beginTime = new Date(); 
for ( i = 0; i < count; i++ ) { 
o = JSON.parse( jsonString ); 
} 
Console.output( "native:" + ( new Date() - beginTime ) ); 
} else { 
Console.output( "native:not support!" ); 
} 
//wrapper 
var __json = null; 
if ( typeof JSON !== "undefined" ) { 
__json = JSON; 
} 
var browser = Browser; 
var JSON = { 
parse: function( text ) { 
if ( __json !== null ) { 
return __json.parse( text ); 
} 
if ( browser.gecko ) { 
return new Function( "return " + text )(); 
} 
return eval( "(" + text + ")" ) 
} 
}; 
beginTime = new Date(); 
for ( i = 0; i < count; i++ ) { 
o = JSON.parse( jsonString ); 
} 
Console.output( "wrapper:" + ( new Date() - beginTime ) ); 
//alert( o.value.items[0].z ); 
</script> 
</body> 
</html>
Javascript 相关文章推荐
onpropertypchange
Jul 01 Javascript
基于jquery的cookie的用法
Jan 10 Javascript
php的文件上传入门教程(实例讲解)
Apr 10 Javascript
Backbone.js中的集合详解
Jan 14 Javascript
让JavaScript中setTimeout支持链式操作的方法
Jun 19 Javascript
javascript精确统计网站访问量实例代码
Dec 19 Javascript
基于Vue.js的表格分页组件
May 22 Javascript
jQuery基于ajax操作json数据简单示例
Jan 05 Javascript
使用angular-cli webpack创建多个包的方法
Oct 16 Javascript
Angular 中使用 FineReport不显示报表直接打印预览
Aug 21 Javascript
用js限制网页只在微信浏览器中打开(或者只能手机端访问)
Dec 24 Javascript
CKEditor扩展插件:自动排版功能autoformat插件实现方法详解
Feb 06 Javascript
TextArea 控件的最大长度问题(js json)
Dec 16 #Javascript
比较详细的关于javascript 解析json的代码
Dec 16 #Javascript
JQuery读取XML文件数据并显示的实现代码
Dec 16 #Javascript
js实现页面打印功能实例代码(附去页眉页脚功能代码)
Dec 15 #Javascript
jQuery 渐变下拉菜单
Dec 15 #Javascript
多浏览器兼容的获取元素和鼠标的位置的js代码
Dec 15 #Javascript
讨论javascript(一)工厂方式 js面象对象的定义方法
Dec 15 #Javascript
You might like
PHP 实例化类的一点摘记
2008/03/23 PHP
使用php shell命令合并图片的代码
2011/06/23 PHP
PHP实现对二维数组某个键排序的方法
2016/09/14 PHP
js 禁止选择功能实现代码(兼容IE/Firefox)
2010/04/23 Javascript
jquery阻止冒泡事件使用模拟事件
2013/09/06 Javascript
详解JavaScript正则表达式中的global属性的使用
2015/06/16 Javascript
js+HTML5实现视频截图的方法
2015/06/16 Javascript
javascript实现网页字符定位的方法
2015/07/14 Javascript
多功能jQuery树插件zTree实现权限列表简单实例
2016/07/12 Javascript
JS遍历ul下的li点击弹出li的索引的实现方法
2016/09/19 Javascript
JS基于递归实现倒计时效果的方法
2016/11/26 Javascript
对称加密与非对称加密优缺点详解
2017/02/06 Javascript
backbone简介_动力节点Java学院整理
2017/07/14 Javascript
JS解决IOS中拍照图片预览旋转90度BUG的问题
2017/09/13 Javascript
Nuxt升级2.0.0时出现的问题(小结)
2018/10/08 Javascript
node实现简单的增删改查接口实例代码
2019/08/22 Javascript
细说webpack6 Babel的使用详解
2019/09/26 Javascript
vue实现在线翻译功能
2019/09/27 Javascript
基于aotu.js实现微信自动添加通讯录中的联系人功能
2020/05/28 Javascript
python学习之面向对象【入门初级篇】
2017/01/21 Python
Python图像处理实现两幅图像合成一幅图像的方法【测试可用】
2019/01/04 Python
torch 中各种图像格式转换的实现方法
2019/12/26 Python
从训练好的tensorflow模型中打印训练变量实例
2020/01/20 Python
tensorflow实现读取模型中保存的值 tf.train.NewCheckpointReader
2020/02/10 Python
python3中sorted函数里cmp参数改变详解
2020/03/12 Python
python实现单机五子棋
2020/08/28 Python
详解修改Anaconda中的Jupyter Notebook默认工作路径的三种方式
2021/01/24 Python
奥地利时尚、美容、玩具和家居之家:Kastner & Öhler
2020/04/26 全球购物
shallow copy和deep copy的区别
2016/05/09 面试题
护理实习自我鉴定
2013/12/14 职场文书
小区门卫管理制度
2014/01/29 职场文书
运动会入场解说词
2014/02/07 职场文书
2014个人四风对照检查材料思想汇报
2014/09/18 职场文书
学术研讨会主持词
2015/07/04 职场文书
《中彩那天》教学反思
2016/02/24 职场文书
redis缓存存储Session原理机制
2021/11/20 Redis