Memory-related performance issues

Memory-related issues are the hardest to debug and solve, and unfortunately, they are also the most likely to be encountered when you first start using Backbone. Again, this is not because Backbone itself has memory issues, but because the possibilities that Backbone enables can allow developers to shoot themselves in the foot if they're not careful.

However, before we proceed, it's important to first explain just how browsers manage memory. As you probably already know, the memory in JavaScript is managed by the browser, not the developer, using something called garbage collector. What this means is that you don't have to tell the browser I'm done using this variable. Instead, you can simply stop using that variable and the browser will figure out that it has become garbage, which will usually make it clean that variable up automatically.

The problem is that the garbage collector operates on a very simple interpretation of what is or is not garbage. In essence, any variable that is not referenced by another variable is considered to be garbage. For instance:

var bookReference = {
    fakeBook: new Book({title: 'Hamlet, Part 2: The Reckoning'})
};
delete bookReference.fakeBook;
// fakeBook has no references, and will be collected as "garbage"

The problem is that developers often don't realize when they leave behind references to a variable, and as such, they force the browser to keep using its memory even though the programmer considers it garbage. Let's look at an example:

var exampleModel = new Backbone.Model();
var exampleView = new Backbone.View();
exampleModel.on('change', exampleView.render);
$(document.body).append(exampleView.el);
exampleView.remove();
// exampleView will NOT be garbage collected

In this example, it seems like we eliminated all references to exampleView when we called exampleView.remove() and removed it from the DOM, but in fact, there was still one reference left behind, hidden inside exampleModel. This reference was created when we called the on method of exampleModel and passed it exampleView.render. By doing so, we told the Model to wait until a change happens and then call exampleView.render, which required it to store a reference to exampleView.render. Since we didn't delete exampleModel, this reference remains and won't be garbage-collected, leaving a so-called zombie View in the browser's memory.

One way to solve this problem would be to remove this reference manually by using the off method:

example.model.off('change'),

However, having to manage such references can quickly become tedious. Luckily, the creators of Backbone added a method to View (as well as the other three Backbone classes) that helps solve this problem, called listenTo. This method works very similarly to on with two important differences. First, it is called on the listening object (in this case, the View), rather than on the object being listened to (in this case, the Model), and second, it does not take a context argument. Instead, the context of the callback will always be set to the object that listenTo was called on.

Just as there is an off method for on, there is a stopListening method that removes listeners created by listenTo. However, you won't need to call stopListening yourself very often, because it's called automatically as part of the remove method of a View, which is what makes it so convenient.

Let's retry our last example using listenTo:

exampleModel = new Backbone.Model();exampleView = new Backbone.View();
exampleModel.listenTo('change', exampleView.render);
$(document.body).append(exampleView.el);
exampleView.remove();
// exampleView WILL be garbage collected

This time, just as before, we have a View listening for changes in a Model. However, because we used listenTo instead of on, the reference created as a side effect will get removed whenever stopListening is called. Since we called remove on exampleView and since this method automatically calls stopListening for us, our View gets garbage-collected correctly without us having to do any extra work.

Unfortunately, however, listenTo can't solve all potential leaky references. For one thing, you may still want to use the on method from time to time. The primary reason for doing so is to listen for events from non-Backbone code, such as a jQuery UI widget. You might also be tempted to use on because (unlike listenTo) it takes a context argument, but thanks to Underscore's bind method, you don't need to do so; you can simply bind your desired context in your callback function before passing it to listenTo. However, even if you do avoid using on entirely, you still have to remember to call remove on your View. If you don't, you still need to use off or stopListening to clear the event binding references. Finally, event handlers aren't the only source of references.

For instance, parent Views and child Views often reference each other, and unless you delete the referencing Views entirely, the Views that it references won't actually be garbage-collected. The good news is that there's no need to worry too much about such references on a small scale, and in fact, trying to optimize performance too heavily on every last bit of code in your application can wind up being counterproductive. Any given Model or View will normally take up only a small amount of memory on its own, so even if you do create a leaky reference that prevents it from being garbage-collected, the actual effect on your application's performance will be minimal. If the user never even notices the leak and then reclaims the memory when he closes his browser or hits refresh, then clearly there was no need for you to have spent time worrying about it.

Instead, you mainly want to focus on managing your references when dealing with large numbers of objects. If you are designing a page View that will be used throughout your application, or creating a View for a large table with many separate child Views, then you will likely want to be extra careful with each reference you create and ensure that all these references get cleaned up when you are done with them.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.148.104.149