Saturday, April 26, 2014

Why is AngularJS slower with jQuery?

(All data in this blog post is based on profiling on an iPhone5 with iOS 7.1)

TL;DR: AngularJS's JQLite has significantly faster .data() and .text()

In jQuery makes AngularJS 50% slower on an iPhone I showed the performance difference between AngularJS with jQuery and AngularJS without jQuery. That 50% was with AngularJS 1.2 and jQuery 1.11 - with AngularJS 1.3 (beta6) and jQuery 2.1 the difference was 35%.

I did a bit of testing to see if there was a simple reason for the slowdown, and turns out that there is. With two changes I got the difference down to 8% (created using The Mobile HTML5 Rendering Profiler; click for a large view):

The changes were to comment out most uses of .data() from AngularJS and changing ng-bind to use a simple inlined code to change the element text instead of jQuery's .text(). Note that these are not 'fixes' that can be applied to AngularJS - they don't preserve all the functionality. What they are is a way to see what is causing the slowdown. Here's the diff:

--- angular-1.3.0-beta.6.js 2014-04-26 16:02:35.000000000 +0300
+++ angular-1.3.0-beta.6-hacked.js 2014-04-26 15:57:23.000000000 +0300
@@ -6007,7 +6007,7 @@
           : $compileNodes;
         forEach(transcludeControllers, function(instance, name) {
-          $'$' + name + 'Controller', instance);
+          //$'$' + name + 'Controller', instance);
         // Attach scope only to non-text nodes.
@@ -6015,7 +6015,7 @@
           var node = $linkNode[i],
               nodeType = node.nodeType;
           if (nodeType === 1 /* element */ || nodeType === 9 /* document */) {
-            $linkNode.eq(i).data('$scope', scope);
+            // $linkNode.eq(i).data('$scope', scope);
@@ -6105,7 +6105,7 @@
           if (nodeLinkFn) {
             if (nodeLinkFn.scope) {
               childScope = scope.$new();
-              $'$scope', childScope);
+              // $'$scope', childScope);
             } else {
               childScope = scope;
@@ -6572,9 +6572,9 @@
           isolateScope = scope.$new(true);
           if (templateDirective && (templateDirective === newIsolateScopeDirective.$$originalDirective)) {
-            $'$isolateScope', isolateScope) ;
+            // $'$isolateScope', isolateScope) ;
           } else {
-            $'$isolateScopeNoTemplate', isolateScope);
+            // $'$isolateScopeNoTemplate', isolateScope);
@@ -6677,7 +6677,7 @@
             // later, once we have the actual element.
             elementControllers[] = controllerInstance;
             if (!hasElementTranscludeDirective) {
-              $'$' + + 'Controller', controllerInstance);
+              // $'$' + + 'Controller', controllerInstance);
             if (directive.controllerAs) {
@@ -18914,12 +18914,13 @@
 var ngBindDirective = ngDirective(function(scope, element, attr) {
-  element.addClass('ng-binding').data('$binding', attr.ngBind);
+  element.addClass('ng-binding'); // .data('$binding', attr.ngBind);
   scope.$watch(attr.ngBind, function ngBindWatchAction(value) {
     // We are purposefully using == here rather than === because we want to
     // catch when value is "null or undefined"
     // jshint -W041
-    element.text(value == undefined ? '' : value);
+    element[0].textContent = (value == undefined ? '' : value);
+    // element.text(value == undefined ? '' : value);

The test is comparing The version without jQuery to the version that loads jQuery before AngularJS; both with the above changes to use of .text() and .data(). Commenting out .data() took the difference from 35% to 20%, and changing .text() from 20% to 8%.

This simple test only really uses ng-repeat and ng-bind. Although these are important parts of AngularJS, a typical application will quite likely use ng-class, ng-if, ng-switch, ng-show etc. These might also show similar slowdowns with jQuery.

It would be interesting to try and optimize these two methods in jQuery, implementing them along the lines of what AngularJS does. I'm not really familiar enough with jQuery to know if there are some real semantic differences in how they are supposed to work (in comparison to AngularJS).

Oh, and I did first think there might be a difference in Garbage Collection, but that was clearly not the case (this is a Timeline image from running with jQuery, there is no GC drop in the memory usage during the rendering, only on the page reload):

Note that the Profiler lets you see Timelines from the iPhone in the (better) Chrome Developer Tools.


Unknown said...

For .text(), I suspect Angular is faster because it doesn't clean up after any elements removed from the document as a result of setting text on the element. That's potentially a bug in Angular.

For .data(), Angular does not get data attributes which makes it faster but not compatible with jQuery, see .

Mika Raento said...

Thanks @Dave Methvin - that's a great answer to my wondering above!

Kiruthiprabha said...

This is most informative and also this post most user friendly and super navigation to all posts... Thank you so much for giving this information to me.. 
Oracle DBA Online Training

rithiaanandh said...

It is amazing and wonderful to visit your site. Thanks for sharing this information, this is useful to me...Resources like the one you mentioned here will be very useful to me! I will post a link to this page on my blog. I am sure my visitors will find that very useful.
Sql server dba online training

sasireka said...

Thank you for benefiting from time to focus on this kind of, I feel firmly about it and also really like comprehending far more with this particular subject matter. In case doable, when you get know-how, is it possible to thoughts modernizing your site together with far more details? It’s extremely useful to me

ReactJS Online Training

jothikumar said...

This is a nice article here with some useful tips for those who are not used-to comment that frequently. Thanks for this helpful information I agree with all the points you have given to us. I will follow all of them.
Software testing online training

Jack sparrow said...

This post is really nice and informative. The explanation given is really comprehensive and informative. I want to share some information about the best oracle dba training and weblogic server tutorial training videos. Thank you .Hoping more articles from you.

lavanya said...

Really you have done great job,There are may person searching about that now they will find enough resources by your post
Software Testing Training in Chennai | Software Testing Training in Anna Nagar | Software Testing Training in OMR | Software Testing Training in Porur | Software Testing Training in Tambaram | Software Testing Training in Velachery

Cho co said...

Along with that, you can recruit a social media company to help you with the promotional tasks. However, you need to ensure that the game is not boring or complicated in any manner. Resurge Pills

radhika said...

Really you have done great job,There are may person searching about that now they will find enough resources by your post

AWS training in Chennai

AWS Online Training in Chennai

AWS training in Bangalore

AWS training in Hyderabad

AWS training in Coimbatore

AWS training

Sages Marketing said...

Very interesting blog. Many blogs I see these days do not really provide anything that attracts others, but believe me the way you interact is literally awesome.You can also check my articles as well.

Security Guard License
Ontario Security License
Security License Ontario
Security License

Thank you..