VueJS Memory Leak when Switching Routes - javascript

Whenever I switch routes, I have noticed that Vue components in my application are never destroyed and only created (the # Deleted column is always 0 as I toggle between routes). To be extra clear, the number of new components created is always equal to the number of components displayed on that route i.e. NONE of the Vue components are ever destroyed and every component on the route is recreated when a route is revisited.
I've been researching to debug the problem and I know that the following are usually culprits of memory leaks in VueJS.
The use of a Global Event Bus and failure to unregister the callback. This is detailed clearly here. While I do use a Global Event Bus in some areas of my application, I'm also experiencing memory leaks on pages where I don't create any event listeners on the Global Event Bus, which leads me to believe that this is not the issue here.
Failure to manually clean up memory yourself when using 3rd party libraries, a problem outlined by the VueJS documentation. Again, I've been looking at memory usage on pages that do not use third party libraries and I'm still getting memory leaks on those.
There is one more potential issue I've come across which I don't quite understand. In this github thread, the OP said the following in regards to potential causes of memory leaks in VueJS:
So I made sure I wasn't doing anything stupid like storing a reference
to this on a Vuex Store...
Can someone please explain what the OP means here in regards to Vuex and memory leaks?
Additionally, what are some other potential issues that cause memory leaks in VueJS that I have missed that could be affecting my application?
How else should I be debugging my memory leak outside of using the Memory tab in Chrome devtools?

Memory is such a pain to debug and your logs look curiously similar to mine.
What i found was be careful of your logs :
console.log(vuecompoent) actually stores your component in memory and does not release it.
Also consider that I turned off vue dev tools as well, but im not sure if this was causing the issue .
Look into the retainers section . This may give you some insight.

Related

Can Observables cause memory leaks if page is closed?

Sorry for the beginner question, but this is one where I'm a bit confused, and couldn't find documentation about. So I understand that if you subscribe to an observable, it can cause memory leaks if not unsubscribed from (for example in OnDestroy since I use mainly Angular). But, is it still a problem if you close the tab/page? As I'm aware of, the server which the app is on is not running it, just serves the frontend code to the browser, which then runs/loads it. So if you don't unsubscribe properly from an observable, it should still be "destroyed" after you close the tab that the app is running on, right? I'm not sure how the browser manages to store these exactly, so I'm not 100% in this, but it sounds logical to me, since apps are most of the time not running 24/7, it's only a problem where it does run all day long, right? (And yes I know we should unsubscribe everytime, I just ask this because of my curiosity).
Similar questions were asked before: with rxjs and angular, Is it necessary to unsubscribe for the subscriptions that happen only once in app component's onInit method?
Also here is an explanation in which the memory leaks are reproduced and why it was necessary to unsubscribe. I have taken the code present on that url and added it to stackblitz for reference. You can uncomment the code to unsubscribe the observable and refresh the url.
The conclusion that I understood from this is after closing the tab, there should not be any memory leaks.

How do I check objects, subscriptions, network requests pending cleanup after React component unmount?

Is there a way to see unnecessary objects still in memory or pending network requests after the React component has unmounted?
If I can see that then I can handle that in componentWillUnmount().
Amir Saleem already mentioned Axios for handling requests. I don't think, that you need to be very concerned about garbage collection in JavaScript as the language interpreter does that for you.
That is a huge difference to C/C++ or some other low level languages where you are responsible for creating and deleting unused memory space.
Just put in the time to use good, tested and efficient algorithms in your code and let the Garbage Collector do the rest. Your whole component will be garbage collected if you're no longer using it.
If you really want an overview of the objects in your application, Firefox has a Memory feature in the developer console. It looks like that:
See more information on Memory Management. Avoiding Memory Leaks in NodeJS might also be interesting for you. Please see also the references on the bottom of the last page.

Ways to identifies memory leaks' origin in Angular app

I'm fairly new to browser's memory management, and memory leaks.
I am making a web app using Angular.js which uses web services to get Model.
Plus, all controllers are linked to templates with ngRoutes except one. It is the controller of my app's main menu which also provide additional logic to router. I inject into each controller this MenuController.
One part of my app needs to check often if there are new informations, to make report. I implemented this as a function based on a $timeout which fires himself inside the function.
I have some trouble cause I found out that my app has some memory leaks and makes crash the browser after 5-6 hours of non refresh. I can see it in Chrome and Firefox but I don't know how to solve this issue.
Which steps should I go forward ?
Thanks.
For memory leak in Angular, I would recommend reading this article.
Also check the way you are using ng-repeat (if you do so) in your app… this is a common source of leak when you don't use the 'track by' syntax.

Trace the execution of ALL Javascript in a web app

Here is the situation: A complex web app is not working, and it is possible to produce undesired behavior consistently. The cause of the problem is not known.
Proposal: Trace the execution paths of all javascript code. Essentially, produce two monstrous logs which can then be fed into a diff algorithm to determine where the behavior related to the bug begins to diverge (as the cause is not apparent from application behavior, and both comprehending and obtaining a copy of the actual JS code being run is difficult, due to the many pages that must be switched to and copied out from the web inspector. Making it difficult is the fact that all pages are dynamically spliced together with Perl code, where significant portions of JS code exist only as (dynamic...) Perl strings).
The Web Inspector in Chrome does not have an option that I know about for logging an execution trace. Basically what I would like is a log of every line of JS that is executed, in the order that they are executed. I don't see this as being a difficult thing to obtain given that the JS VM is single-threaded. The problem is simply that the existing user-facing tools are not designed for quite this much hardcore debugging. If we look at the Profiler in the Dev Tools, it's clearly capable of the kind of instrumentation that I need, but it is fundamentally designed to do profiling instead of tracing.
How can I get started with this? Is there some way I can build Chrome from source, where I can
switch off JIT in V8?
log every single javascript expression evaluated by V8 to a file
I have zero experience with the development side of Chrome. So e.g. links to dev-builds/branches/versions/distros of Chrome/Chromium/Canary (what's the difference?) are welcome.
At this point it appears that instrumenting the browser with powerful js tracing is still likely to be easier than redesigning the buggy app. The architecture of the page is a disaster, but the functionality is complex, and it almost fully works. I just have to find the one missing piece.
Alternatively, if tools of this sort already exist, what are some other keywords I can search for them with? "Code Tracing" is pretty much the only thing I can come up with.
I tested dynaTrace, which was a happy coincidence as our app supports IE (indeed Chrome support just came out of beta), but this does not produce a text dump, it basically produces a massive Win32 UI expando-tree, which is impossible to diff. This makes me really sad because I know how much more difficult it was to make the representation of the trace show up that way, and yet it turns out being almost utterly useless. Who's going to scroll up and down that tree view and see anything really useful in it, in anything other than a toy example of a web app?
If you are developing a big web app, it is always good to follow a test driven strategy for the coding part of it. Using just a few tips allows you to make a simple unit testing script (using QUnit) to test pretty much all aspects of your app. Here are some potential errors and some ways of solving them.
Make yourself handlers to register long living Objects and a handler to close them the safe way. If the safe way does not succeed then it is the management of the Object itself failing. One example would be Backbone zombie views. Either the view has bad code in the close section, the parent close is not hooked or an infinite loop happened. Testing all view events is also good, although tedious.
By putting all the code for data fetching inside a certain module (I often use a bunch of Backbone.Model objects for each table/document in my DB) and handlers for each using a reqres pattern, you can test them 1 by 1 to see if they all fetch and save correctly.
If complex computation is needed, abstract it in a function or module so that it can be easily tested with known data.
If your app uses data binding, a good policy is to have a JSON schema for all data to be tested against your views containing your bindings. Check against the schema all the data required. This is applied to your Backbone.Model also.
Using a good IDE also helps. PyCharm (if you use Python for backend) or WebStorm are extremely good for testing and developing JavaScript/CoffeeScript. You can breakpoint and study your code at specific locations, inside your browser! Also it runs your code for auto-completion and you can see some of the errors that way.
I just cannot encourage enough the use of modules in your code. Although there is no JavaScript official way of doing it (next ECMAScript draft has it), you can still use good libraries for it. Good ones are: RequireJS, CommonJS or Marionette.Module (if you use Marionette as your framework). I think Ember/AngularJS also offers this kind of functionality but I did not work with them personally so I am not sure.
This might not give you an immediate solution to your problem and I don't think (IMO) there is an easy one either. My focus was to show you ways to develop so that errors can be easily spotted and countered, and all of it (depending on your Unit Testing) during development phase. Errors will always happen, as much as our programmer ego wants us to believe the contrary. Hope I helped :)
I would suggest a divide and conquer strategy, first via logging, and second via code. Wrap suspect methods of the code with console logging in and out events and when the bug occurs hopefully it is occurring between or after some event. If event logging will not shed light, bring parts of the code into a new page/app. Divide and conquer will find when the error starts occurring.
So it seems you're in the realm of weird already, so I'm thinking of a weird solution. I know nothing about the backend of chrome myself so we're in the same boat, but if you're feeling bold here's an idea. Maybe you could find/replace every newline in your javascript files with a piece of code that logs either to a global string or to the console a) what file you're in, b) the contents of "this" or something useful to you, and maybe even c) the time. This would at least get you started. Make sure it's wrapped in something distinct so you can just as easily remove it.

Big performance issues/crashing using backbone on mobile phones

we have built our service dailymus.es to be mobile friendly, but we are hitting on a range of performance issues when accessing it on the mobile phone.
Specifically, it crashes after a few "pages" and when we have a lot of content on the page.
I am suspecting that we have too many event handlers and/or memory leaks. What methods do you use to eliminate these problems with Backbone?
I suggest you test your site using Google Chrome's Developers Console. Use the Profile tab to examine the state of the heap.
Most leaks of backbone models/views are due to not detaching the DOM events from views and the binding (on) events from models.
Make sure to override the remove method of your backbone view and make sure you .off() from everything you set to .on(). Don't forget to call remove on sub-views.
To find leaks:
Take a snapshot
Run your code to create a view and then remove it
Take another snapshot
Compare the snapshots to find the new objects created who weren't released.
More about the Google Chrome Heap Profiler
Backbone wastes a lot of memory which is the hardest thing for mobile. There's a lot of techniques for object pooling on the DOM elements, updating elements instead of recreating templates, limit loading images until the last minute, holding any updates until right before the paint cycle.
Mobile web can be performant if the memory is managed properly. PrefView is a good example and can get 50FPS on long scroll list on an iPad mini. https://github.com/puppybits/BackboneJS-PerfView

Categories