How do you figure out the bottle necks in an AngularJS app? - angularjs

AngularJS batarang is unusable. It freezes and is unresponsive. How do you figure out where the bottlenecks are? What kind of tools can I use to profile my application to figure out if its my directives or if I have too many watchers?

This problem is perhaps caused, because you broke the watch-apply-digest cycle of the Angular framework by causing digest cycles where they should not be. This can cause Angular to create almost infinite loops watching variables for refresh, thus making your app really slow. But you can confirm that by just disabling Batarang, since the app would be slow by its own.
Anyway, if your app is efficient and only Batarang creates this issue, you can skip using it and start debugging with developer tools. I have also switched to this path various times and I can say it is quite fast (I did not expect it either). To follow this strategy, you have to simply select an element with developer tools and then execute in the JS console :
var scope = angular.element($0).scope()
So, you now have the scope of this element and you can simply check any field you want inside the scope at any time, thus testing the whole watch-apply-digest cycle of Angular.
You can learn more about the watch-apply-digest cycle here

Related

AngularJs: Initial directive rendering is slower

I've done a lot towards optimisation of one part of my application, due to huge amount of elements in DOM. I implemented lazy loading, watched for every digest cycle to be as small as possible, etc.
Now my question is, if anyone else has encountered, that the initial compiling and rendering is slower than rendering for the second time(like navigate to different app location and back again).
Is angular caching somehow and if so, how can I force to cache it in advance?
$Routing in angular is done using $templateRequest which in turn utilizes $templateCache. That's why all consequent template changes looks faster.
Tools like gulp-angular on yeoman.io for example automatically will build your application and place your HTML files in the $templateCache for you. It will also concatenate and minify all of the scripts.
Ultimately what you are looking for is for the html snippets to be all included in that single javascript file so that there arent individual HTML GET requests for each one.

Angular directives causing long load times

We currently have a large complex application build using Angular (1.3).
I have a page that is maybe using 20 custom directives (nested).
I'm finding the load time (angular bootstrap) is very slow especially on android.
Using chrome timeline profiling I can see the angular bootstrap is taking about 800ms on desktop, but about 8 seconds on android (using remote debug).
This is on a fairly new android phone (samsung s5). However on an iPhone 5 (it takes no more than 4 seconds.
My question is does directive compilation have to take that long? I don't think my directives link functions are actually taking long to execute. Will replacing directives withe a combination of ng-include/ng-controller make it better? Will replace 20 directives with one big directive make a difference?
Why would the mobile chrome browser be so less performant than iOS safari browser and very similiar hardware?
Thanks,
It is likely due to the high number of requests a browser makes to render your website. Each directive has a template, so that's 20 requests on top of all the others (js files, images, css etc). You also have to consider that each directive/template is loaded when its parent directive/template is loaded since they are nestled, and this can make a huge impact on performance.
It may also load faster on desktop and varies on mobile based on a browsers simultaneous connection limit. I believe for iOS safari it is 6, and mobile chrome is 4.
You need to reduce the amount of template loading, and ensure you are making use of a browsers cache. In your case it may be better to combine some directives to improve performance.
Your fisrt question
My question is does directive compilation have to take that long?
No. Angularjs can handle much more than 20 custom directives quickly according to my experience.
I don't think my directives link functions are actually taking long to execute.
I think you may run into issues and need to spend time on optimization probably. Maybe too much DOM manipulating or HTML reflow.
Your second question
Will replacing directives withe a combination of ng-include/ng-controller make it better?
I don't think so. ng-include/ng-controller are also directives. There is no essential difference.
Your third question
Will replace 20 directives with one big directive make a difference?
No. The number of directives doesn't matter. What matter is what directive does.
And your last question. It's a fact sucks and torments me long time. I also don't know why.

how to log the boot time for each controller and directive

I'm optimize my angular app. I found that only bootstrap the angular app will cost hundred milliseconds.
console.time("ng-boot");
angular.bootstrap("myapp");
console.time("ng-boot");
the time is nearly 300ms!!!
then I want to get all the running time of each controller(init) and directive(postLink maybe...), during the "bootstrap" phase. how can I achieve that?
of course I can get the time by adding logs in every controllers and link functions in directives. but I have too many directives. I want to know if there is a better way.
personally i suggest you use chrome developer tools, profiles tab.
it has great tools to check speed, memory, cpu. much better than console.log everywhere.

Feasibility of using angular js for web app with over 200 medium to complex screens

My team was considering using angular js for web app UI development. But knowing at a high level how single page apps work, I had a question as to, how feasible it is to use angular js framework, for a large web application. this would have at least 200 screens, each screen containing an average of 30 UI controls like text boxes, calendar controls, drop downs etc.
The user will be accessing the web app on desktop or laptop and will be using the application in the browser throughout an 8 hour day, without ever closing the browser.
Given above usage, would angular js, memory usage / performance be issue?
are there web apps with huge and complex UI, built using angular js, that are in production and used everyday?
You can have not just 200 but 1000's of screens - this number does not matter as long as you address the core and fundamental questions below. They all boil down to memory and performance.
At a given point of time how many $watches will be active.
At a given point of time how many listeners are created.
At a given point of time what is the complexity of DOM i.e. the number of DOM elements and thee nesting/depth.
At a given point of time how many Javascript modules (services, controllers etc.) will be loaded in the memory. Even though these things are singletons they consume memory.
For each such screen how much memory will be consumed (if you use jqueryUI etc. your memory increases quite rapidly than pure angular + html components)
This brings to what you can do to control the above factors which if not watched will make your application sink/crash.
1) How do you break the run-time complexities of your "big" application ? You can now think of "Routers" or dialogs. Each of your screen will come-and-go i.e. you will never display 200 screens the same time.
2) Make sure when the screen is gone there is no "leftover". Don't use jQuery - if you do make sure you clean this on $scope.$destroy.
3) Multitudes of directives:- Directives are powerful but don't over use it - try not to deep nest too many of them. templateUrl is "tempting" but sometimes in-lining a template is the best choice. Use build tools that will inline the templates.
4) Load modules on demand using requireJS. This will force you to modularize your application and think hard about concatention strategy (combining JS files). Will force you to write independent modules.
5) Browser caching your assets and a good cache busting mechanism. Grunt based plugins are to your rescue. Minify your assets.
6) Compresss the assets for efficient network utilization and faster transmission.
7) Keep your app encapsulated in Angular. Don't create any global objects. Chances are that they have access to some closure or are referring to some things within angular $scope and $scopes are now still hanging on or are in difficult trajectory to be able to get Garbage Collected.
8) Use one-time-bind or bind-once model binding as much as possible.
9) Splash screen is an excellent weapon - us it. Helps you load some stuff upfront while the user watches smooth/jazzy picture/picture :)
Regarding 8 hours a day constant use
Unless there is a leak of the following kind you should be fine:-
1) Listeners leaking i.e. hanging around.
2) DOM leaks. Detached DOM issue.
3) Size of Javascript objects. Javascript objects coded in a certain way creates repeated instances of function.
(I am developing AngularJS app - with more than 450 screen - MDI like app. The app is not yet in production. The above points are coming from my burnouts in the functionality we have developed so far.)
I've worked on multiple projects that are extremely large single-page applications in Angular and Ember.JS at companies like McKesson an Netflix.
I can tell you for a fact that it's completely "feasible" to build "huge, complex" applications with frameworks such as Angular. In fact, I believe Angular is uniquely well suited to this because of it's modular structure.
One thing to consider when creating your Angular application is whether or not every user will benefit from all "200 pages" of your application. That is to say, is it necessary to have all 200 views be part of the same single page application? Or should you break it into a few single page applications with views that share concerns.
A few tips:
Watch out for name collisions in the IOC container: If you create enough services and controllers, even if you break them into separate modules, it's very easy to create two services with the same name. This may or may not result in an outright error. What happens when you register two "fooService" services? The last one wins.
If you decide to break your app into more than one single page app, you have to be sure you have solid boundaries of functionality between the two. They're not going to be able to share state easily other than with something like cookies or local storage.
If you decide to keep everything in one single page app, you're going to want to keenly watch your initial download time. Always check to see how long it takes to start your app "cold" over a slow-ish connection. If the entire app is in one bundle, depending on how you structure things (are you going to use AMD?) then you might see a long initial load time.
AVOID rendering HTML on your server. I can't stress this enough. Let Angular do that work for you. The only rendering your server should be doing is rendering JSON to be returned from some RESTful service.
Flush out your JS build process early on. Look into Node-based tools like Grunt, Gulp, and Broccoli for linting/concatenating/minifying your JS files. Checkout Karma for running unit tests, and look into Istanbul for code coverage. Protractor is a great tool as well, but I recommend strong unit tests in Karma over integration tests with Protractor just because Web Driver based tests tend to be brittle.
Other than that, I think you'll find a single page app written in any modern framework to be extremely snappy after the initial load is done. In fact, it will make any "old" PHP/ASP.Net style app that renders the entire page at the server seem slow as dirt in comparison. This is because you'll only be loading data and the occasional .html file over HTTP.

Testing RequireJS application with FluentAutomation?

I'm attempting to write some UI tests for a RequireJS-based Backbone application, utilizing FluentAutomation.SeleniumWebDriver and NUnit. The HTML page in question contains a typical data-main attribute for loading the RequireJS module for the application. My struggle is in properly detecting when the application is fully loaded with these tools; the only thing I've gotten to work consistently so far is using an explicit wait in seconds, like so:
I.Open("http://myapp")
.Wait(5)
.Enter("foo").In("input[name=username]")
.Enter("bar").In("input[name=password]")
.Click("button")
.Wait(5)
.Expect.Text("Welcome").In("#welcome");
This is less than ideal -- my test as written above will always take at least 10 seconds to run, when in reality the app might be "ready" much faster than that. What I'd like to be able to do is something like this:
I.Open("http://myapp")
.WaitUntil(() => I.Assert.Exists("input[name=username]"))
.Enter("foo").In("input[name=username]")
.Enter("bar").In("input[name=password]")
.Click("button")
.WaitUntil(() => I.Assert.Exists("#welcome"))
.Expect.Text("Welcome").In("#welcome");
However, this doesn't work -- using WaitUntil here actually seems to prevent the app from loading, for reasons unclear to me, as I simply receive timeout exceptions after the default wait period (30 seconds), stating that it was unable to locate the element in question within that timeframe.
I see that Selenium 2 provides a WebDriverWait for this kind of scenario, and possibly that would work here, but am unsure how I would use this within FluentAutomation (and a quick search of the FluentAutomation code on GitHub doesn't seem to indicate it's in use within the library).
What can I use in FluentAutomation to properly wait for a RequireJS module (or DOM loaded by it) to be ready?
Additional details:
This might not be a RequireJS compatibility problem at all. I've looked further into the app and found that what's happening after the Click("button") is actually a window.location.replace -- not a RequireJS async module load. It's the one place in the app that this is occurring, apparently. So, is a window.location redirect a known scenario that would cause problems with WaitUntil, and is there an alternate approach (aside from a simple Wait(5)) that would properly handle this?

Resources