JS performance test - scope and named functions - Analytics
JavaScript global scope vs. encapsulated, variable as holder of anonymous function vs. named functions.
This stress test gave quite a surprise. Popular JS coding practices and dominant opinion appeared to be completely wrong. Probably because of rapid evolution of JS engines. Or maybe the habit to rely on reasonable guesses of respected people.Idea
To create the test came from inconvenience of using anonymous code. There are many code maintenance reasons to switch to named functions code but on the net many respected JS gurus are promoting the anonymous functions use and most popular JS library are filled with such code. Is there any compromise with widely accepted pattern? If the speed lost is not big, choice could be balanced.Appeared I was wrong in my expectations. All tests shown there is no need for balance. Old fashion coding style shall be considered as bad practice and removed from code as harmful.
Conclusion
- Use the named function instead of variable initialized with anonymous function.
- Global functions given much boost in performance. Reduce the use of scoped functions for initialization code - page initialization code wrapped into own scope way slower of global functions declaration.
- Use SCRIPT dom node code injection instead of slower eval().
The Web 2.0 application consists not just from JS initialization. In fact, it is just 1st row developer facing for page load and run speed. In most cases frameworks are "good enough" on their own. The problems usually appeared in heavy apps utilized several of them simultaneously.
Test.
Initially had simple evaluation purpose for anonymous functions replacement with named ones. Code maintenance is badly damaged by such coding style and test shall show if performance is not a real issue.For test JSP renders identical JS code with only difference on function declaration signature
Var as reference to anonymous function:
var
FunctionScr3Var27=function(){ window.RealCount++; }
var function FunctionScr3Var27(){ window.RealCount++; }
Another thought was about having the size of rendered file in stats. XHR gives its string value and length. And that could be used for eval() timing. The known fact is “eval() slower of SCRIPT tag”. Question is how much?
Not sure what given me the idea to run the same test inside of function scope in addition to just global one. But surprising results came out of it.
Speculation on statistics.
1. Anonymous function vs. named functions. Test cases: 0,1,4,5 versus 2,3,6,7IE: functions are 10-200% faster
Opera: run time so damn fast that no way to detect the difference. Same.
Chrome: function 10% faster in local scope. Same
FF: on edge of detection. Same
Safari: Same
2. Global scope vs. wrapped in function. Test cases: 0,1,2,3 vs 4,5,6,7. Global faster:
IE,Opera: 20-300%
Chrome: in eval() local is enormously slow, on run is on the edge of detection. Same w/ favor to global scope.
FF: in eval() local 50% slower, in run untraceable. Same w/ favor to global scope.
Safari:10%
3. Eval() vs SCRIPT . eval looses:
IE: 200-400%
Opera: 1000%
Chrome 10-300%, 1000% for local scope
FF: 700%
Safari 10%
4. Half vs. full set. Meaning TBD. IMHO, that is just JS engine capabilities test,
IE: 20-200%
Opera, Chrome: 5%
FF +=5% (?)
Safari 50% (expected)
5. Browsers overall
Opera is 6 times slower for JS load and parsing time and as result, overall.
JS engine – run time in ms:
Safari: 924 ( worst ).
FF: 23
IE: 17
Opera: 16
Chrome: 10 (best)
JS engine – eval(), ms
Safari: 950
Opera: 560
Chrome: 263
FF: 170
IE: 38(best)
PS It would be nice to integrate real-time charting, but there is not enough bandwidth on my side. Any sponsors or volunteers?
Links
- Genuine post
- Blog
- Statistics data
- Test cases : 500 | 1000 | 3000 | 10000
- Sources: index.jsp - UI file | AnonymousJsVsNamed.js.jsp- JS rendering JSP
Sasha
Hey Sasha,
ReplyDeleteI saw some performance testing being done in this website: http://carlos.bueno.org/2010/02/measuring-javascript-parse-and-load.html?v=2
But yours is definitely more in depth.
Very useful,
Thanks!
Thank you for link. While Carlos made the test on his favorite JS libraries, it does not reflect the actual performance and give many wrong assumptions. The libraries are relatively small and given the test results on JS timer sensitivity limit. 32 milliseconds is not reliable stats when timer could discrete step is around 16ms.
ReplyDeleteThe spikes are not part of test: the delays causes are quite random. From CPU taken by OS background activities to network traffic from embedded ad services or "3rd party browser toolbar". Average mininum above 32ms is what could be counted.