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 相关文章推荐
javascript 密码强弱度检测万能插件
Feb 25 Javascript
16个最流行的JavaScript框架[推荐]
May 29 Javascript
js用拖动滑块来控制图片大小的方法
Feb 27 Javascript
JavaScript ES5标准中新增的Array方法
Jun 28 Javascript
利用JavaScript实现栈的数据结构示例代码
Aug 02 Javascript
vue综合组件间的通信详解
Nov 06 Javascript
微信小程序tabBar模板用法实例分析【附demo源码下载】
Nov 28 Javascript
使用express获取微信小程序二维码小记
May 21 Javascript
vue实现手机号码的校验实例代码(防抖函数的应用场景)
Sep 05 Javascript
vuex的使用和简易实现
Jan 07 Vue.js
jQuery treeview树形结构应用
Mar 24 jQuery
微信小程序中wxs文件的一些妙用分享
Feb 18 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下保存远程图片到本地的办法
2010/08/08 PHP
php时间戳转换的示例
2014/03/31 PHP
php验证是否是md5编码的简单代码
2014/04/01 PHP
PHP检测链接是否存在的代码实例分享
2016/05/06 PHP
Smarty简单生成表单元素的方法示例
2016/05/23 PHP
两个DIV等高的JS的实现代码
2007/12/23 Javascript
Javascript实现的类似Google的Div拖动效果代码
2011/08/09 Javascript
用js的document.write输出的广告无阻塞加载的方法
2014/06/05 Javascript
window.open()实现post传递参数
2015/03/12 Javascript
基于jQuery实现的旋转彩圈实例
2015/06/26 Javascript
如何使用Vuex+Vue.js构建单页应用
2016/10/27 Javascript
JavaScript 深层克隆对象详解及实例
2016/11/03 Javascript
javascript 初学教程及五子棋小程序的简单实现
2017/07/04 Javascript
js前端导出Excel的方法
2017/11/01 Javascript
JavaScript实现短暂提示框功能
2018/04/04 Javascript
Node 升级到最新稳定版的方法分享
2018/05/17 Javascript
Vuex,iView UI面包屑导航使用扩展详解
2019/11/04 Javascript
jQuery 常用特效实例小结【显示与隐藏、淡入淡出、滑动、动画等】
2020/05/19 jQuery
解决antd的Form组件setFieldsValue的警告问题
2020/10/29 Javascript
可用于监控 mysql Master Slave 状态的python代码
2013/02/10 Python
python re正则表达式模块(Regular Expression)
2014/07/16 Python
Python如何抓取天猫商品详细信息及交易记录
2018/02/23 Python
python pandas dataframe 按列或者按行合并的方法
2018/04/12 Python
详解Python安装scrapy的正确姿势
2018/06/26 Python
Python大数据之网络爬虫的post请求、get请求区别实例分析
2019/11/16 Python
python爬虫库scrapy简单使用实例详解
2020/02/10 Python
Python基于jieba, wordcloud库生成中文词云
2020/05/13 Python
Carter’s官方旗舰店:美国受欢迎的婴童服装品牌
2018/01/21 全球购物
平面设计师工作职责范文
2013/12/03 职场文书
公司庆典邀请函范文
2014/01/13 职场文书
探矿工程师自荐信
2014/01/24 职场文书
小学生检讨书大全
2014/02/06 职场文书
报考公务员诚信承诺书
2014/08/29 职场文书
教师群众路线心得体会
2014/11/04 职场文书
Python可视化学习之seaborn调色盘
2022/02/24 Python
Python实现科学占卜 让视频自动打码
2022/04/09 Python