JSON Performance comparison of eval, new Function and JSON
We parse a JSON string to JSON object when we handle response of server in AJAX.We use eval or new Function to parse JSON string normally, and IE8 and Firefox3.1 has a native JSON support( Native JSON parsing is much faster).How can we choose from the three methods in practice? And how can we know whose performance is the best since there are so many browers?
Code & Concern
defined a json string and circle numbers
1: 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
1: var beginTime = new Date();
2: for ( i = 0; i < count; i++ ) {
3: o = eval( "(" + jsonString + ")" );
4: }
5: Console.output( "eval:" + ( new Date() - beginTime ) );
- new Function
1: var beginTime = new Date();
2: for ( i = 0; i < count; i++ ) {
3: o = new Function( "return " + jsonString )();
4: }
5: Console.output( "new Function:" + ( new Date() - beginTime ) );
- native
1: if ( typeof JSON !== "undefined" ) {
2: var beginTime = new Date();
3: for ( i = 0; i < count; i++ ) {
4: o = JSON.parse( jsonString ); }
5: Console.output( "native:" + ( new Date() - beginTime ) );
6: } else {
7: Console.output( "native:not support!" );
8: }
Browsers
It includes IE6, 7 , 8; Firefox2, 3, 3.1; Chrome; Opera and Safari3, 4.
Environment
T9300 CPU + 4G RAM + Windows2003, IE8 in Vista, IE7 in another machine( 2G CPU + 2G RAM + Windows2003 )
Result
*The smaller the number is,the better the result will be.
*The column in green shows the best performance, while in red shows the worst.
Firefox2, 3 gain the worst performance, IE6 better than IE7( may be related with machines ), Chrome and Safari4 are far superior to other browsers.
Genally speaking, eval is better than new Function,though they have different results in different browsers. But the "new Function" is the double performance of eval in Firefox, so we wrap a class to parse json string to gain better performance in cross-browser.
- wrapper
1: var __json = null;
2: if ( typeof JSON !== "undefined" ) {
3: __json = JSON;
4: }
5: var browser = Browser;
6: var JSON = {
7: parse: function( text ) {
8: if ( __json !== null ) {
9: return __json.parse( text );
10: }
11: if ( browser.gecko ) {
12: return new Function( "return " + text )();
13: }
14: return eval( "(" + text + ")" )
15: }
16: };
17: var beginTime = new Date();
18: for ( i = 0; i < count; i++ ) {
19: o = JSON.parse( jsonString ); }
20: Console.output( "wrapper:" + ( new Date() - beginTime ) );
The results with wrapper:
After wrapping, it is slower than before due to the cost, but it offers a guarantee to call better implementation.
Conclusion
We should choose a different method when using different browsers:
- choose eval in IE6, 7
- choose native JSON in IE8
- choose new Function in Firefox2, 3
- choose eval in Safari4
- eval has the same performance as new Function on the whole when you use the other browsers.
Hope this helps,
Andy
Update:
- 2009.03.23: Disabled all Firefox' Add-Ons
someone told me got a different result after he ran the code in Firefox, I doubt Firefox’s Add-Ons conduces to wrong result, so I run it after I disabled Firebug.
We made a mistake in tests about Firefox, but it is not good enough to our without Firebug.
- 2009.03.31: Use different Json strings in the loops
according to Oliver' reply, modify code:
1: for ( i = 0; i < count; i++ ) {
2: 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}' + ")");
3: }
result:
opera is best performance, but Ie8 is better than chrome and safari.
main code:
1: //test code
2: var count = 10000, o = null, i = 0, jsonString = "";
3:
4: //eval
5: var beginTime = new Date();
6: for ( i = 0; i < count; i++ ) {
7: 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}' + ")");
8: }
9: Console.output( "eval:" + ( new Date() - beginTime ) );
10: //new Function
11: beginTime = new Date();
12: for ( i = 0; i < count; i++ ) {
13: 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}')();
14: }
15: Console.output( "new Function:" + ( new Date() - beginTime ) );
16: //native
17: if ( typeof JSON !== "undefined" ) {
18: beginTime = new Date();
19: for ( i = 0; i < count; i++ ) {
20: 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}');
21: }
22: Console.output( "native:" + ( new Date() - beginTime ) );
23: } else {
24: Console.output( "native:not support!" );
25: }
26: //wrapper
27: var __json = null;
28: if ( typeof JSON !== "undefined" ) {
29: __json = JSON;
30: }
31: var browser = Browser;
32: var JSON = {
33: parse: function( text ) {
34: if ( __json !== null ) {
35: return __json.parse( text );
36: }
37: if ( browser.gecko ) {
38: return new Function( "return " + text )();
39: }
40: return eval( "(" + text + ")" )
41: }
42: };
43: beginTime = new Date();
44: for ( i = 0; i < count; i++ ) {
45: 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}');
46: }
47: Console.output( "wrapper:" + ( new Date() - beginTime ) );
Source:
1: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
2: <html>
3: <head>
4: <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5: <title>Parse JsonString</title>
6: </head>
7: <body>
8: <div id="consoleRegion"></div>
9: <script type="text/javascript">
10: //yui
11: var Browser = function() {
12: var o = {
13: ie: 0,
14: opera: 0,
15: gecko: 0,
16: webkit: 0
17: };
18: var ua = navigator.userAgent, m;
19: if ( ( /KHTML/ ).test( ua ) ) {
20: o.webkit = 1;
21: }
22: // Modern WebKit browsers are at least X-Grade
23: m = ua.match(/AppleWebKit\/([^\s]*)/);
24: if (m&&m[1]) {
25: o.webkit=parseFloat(m[1]);
26: }
27:
28: if (!o.webkit) { // not webkit
29: // @todo check Opera/8.01 (J2ME/MIDP; Opera Mini/2.0.4509/1316; fi; U; ssr)
30: m=ua.match(/Opera[\s\/]([^\s]*)/);
31: if (m&&m[1]) {
32: o.opera=parseFloat(m[1]);
33: } else { // not opera or webkit
34: m=ua.match(/MSIE\s([^;]*)/);
35: if (m&&m[1]) {
36: o.ie=parseFloat(m[1]);
37: } else { // not opera, webkit, or ie
38: m=ua.match(/Gecko\/([^\s]*)/);
39: if (m) {
40: o.gecko=1; // Gecko detected, look for revision
41: m=ua.match(/rv:([^\s\)]*)/);
42: if (m&&m[1]) {
43: o.gecko=parseFloat(m[1]);
44: }
45: }
46: }
47: }
48: }
49: return o;
50: }();
51:
52: var Console = {
53: consoleRegion: null,
54:
55: getRegion: function() {
56: if ( this.consoleRegion === null ) {
57: this.consoleRegion = document.getElementById( "consoleRegion" );
58: }
59: return this.consoleRegion;
60: },
61:
62: output: function( text ) { this.getRegion().innerHTML += "<br/>" + text; }
63: };
64: //test code
65: 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}';
66: //eval
67: var beginTime = new Date();
68: for ( i = 0; i < count; i++ ) {
69: o = eval( "(" + jsonString + ")" );
70: }
71: Console.output( "eval:" + ( new Date() - beginTime ) );
72: //new Function
73: beginTime = new Date();
74: for ( i = 0; i < count; i++ ) {
75: o = new Function( "return " + jsonString )();
76: }
77: Console.output( "new Function:" + ( new Date() - beginTime ) );
78: //native
79: if ( typeof JSON !== "undefined" ) {
80: beginTime = new Date();
81: for ( i = 0; i < count; i++ ) {
82: o = JSON.parse( jsonString ); }
83: Console.output( "native:" + ( new Date() - beginTime ) );
84: } else {
85: Console.output( "native:not support!" );
86: }
87: //wrapper
88: var __json = null;
89: if ( typeof JSON !== "undefined" ) {
90: __json = JSON;
91: }
92: var browser = Browser;
93: var JSON = {
94: parse: function( text ) {
95: if ( __json !== null ) {
96: return __json.parse( text );
97: }
98: if ( browser.gecko ) {
99: return new Function( "return " + text )();
100: }
101: return eval( "(" + text + ")" )
102: }
103: };
104: beginTime = new Date();
105: for ( i = 0; i < count; i++ ) {
106: o = JSON.parse( jsonString ); }
107: Console.output( "wrapper:" + ( new Date() - beginTime ) );
108: //alert( o.value.items[0].z );
109: </script>
110: </body>
111: </html>