Douglas Crockford az Internet Explorer memóriaszivárgásokról
Ehhez a blogmarkhoz kapcsolódva legépeltem az IE memóriaszivárgás kezelésére vonatkozó részt az előadásból - most tanulom az AJAX-ot és nagyon hasznosnak találtam. A harmadik előadás elején van, utána is van még néhány jó tippet AJAX témában.
■ There is a problem of event handlers and garbage collection, particularly in IE. Ordinarily we shouldn't have to worry about memory leaks, because Javascript is an automatically managed memory system, which is good, and the browser is too. So we cannot explicitly allocate memory from the browser and de-allocate it - that's all done automatically for us, which is good. Sometimes in a memory-managed system like that it is possible to accidentally hang on to too much state, you might have a variable that contains a reference to a really big structure that you're not using any more, in those cases it's probably a good idea to [...] garbage collector can get out that stuff. Generally it's not a problem, not something that [we have to] worry about, except when there are real errors in the implementation of these things that you do have to worry about it.
The biggest memory leak that we do have to be concerned about is in IE6. So because of that you need to explicitly remove all of your event handlers from your nodes before you remove them from the DOM.
Microsoft didn't think that was a problem, because you don't have cyles in a DOM structre - it's a tree, it's strictly acyclical, so that makes reference counting safe. The thing that they didn't consider was that when you add an event handler to a DOM node, you have a pointer going back to Javascript's space. And in Javascript's space you might also have, say, a variable pointing back to the DOM node. In fact that's pretty likely, because you have to have a reference to the DOM node in order to attach the event handler to it. The way the closures work, generally they will stay bound together. Microsoft has tried to convince the programming community that it's your fault, that you shouldn't be using closures when writing in Javascript, but in that language you cannot avoid using closures. Any time you are using an inner function you are using closures. So avoiding closures is not good advice. So what you have to do is fix it where the problem actually exists. Which is on the DOM side. And you have to do that by explicitly removing the event handlers from the DOM nodes before the DOM nodes get detached. So you have to break those cycles. This wasn't an issue for a long time because applications were page-oriented, you'd show a page, be on the screen for a minute or two, then you go onto another page, and during the time you were on the screen there wasn't all that much script running. So for years nobody noticed that this [...] was going on, because of the usage pattern. But when you're doing Ajax applications, where that page could be on the screen for hours, and you've got intense Javascript running the whole time, it quickly fills up and you get memory starvation and destruction.Or you can use YUI's purgeElement method.
Using our old friend walkTheDOM, we pass it this function. And what this function does, it will look at all the attributes, and if it finds any that look like functions, null them out. And if we call this on an object that we are gonna delete, this will take care of it.
As an alternative, you can use YUI, it has a purgeElement method that will do this for you.
The biggest memory leak that we do have to be concerned about is in IE6. So because of that you need to explicitly remove all of your event handlers from your nodes before you remove them from the DOM.
Memory Leaks on IE6
- Explicitly remove all of your event handlers from nodes before you discard them.
- The IE6 DOM uses a reference counting garbage collector.
- Reference counting is not able to reclaim cyclical structures.
- You must break the cycles yourself.
Microsoft didn't think that was a problem, because you don't have cyles in a DOM structre - it's a tree, it's strictly acyclical, so that makes reference counting safe. The thing that they didn't consider was that when you add an event handler to a DOM node, you have a pointer going back to Javascript's space. And in Javascript's space you might also have, say, a variable pointing back to the DOM node. In fact that's pretty likely, because you have to have a reference to the DOM node in order to attach the event handler to it. The way the closures work, generally they will stay bound together. Microsoft has tried to convince the programming community that it's your fault, that you shouldn't be using closures when writing in Javascript, but in that language you cannot avoid using closures. Any time you are using an inner function you are using closures. So avoiding closures is not good advice. So what you have to do is fix it where the problem actually exists. Which is on the DOM side. And you have to do that by explicitly removing the event handlers from the DOM nodes before the DOM nodes get detached. So you have to break those cycles. This wasn't an issue for a long time because applications were page-oriented, you'd show a page, be on the screen for a minute or two, then you go onto another page, and during the time you were on the screen there wasn't all that much script running. So for years nobody noticed that this [...] was going on, because of the usage pattern. But when you're doing Ajax applications, where that page could be on the screen for hours, and you've got intense Javascript running the whole time, it quickly fills up and you get memory starvation and destruction.
Memory Leaks on IE6
- That was not an issue for page-view driven applications
- It is a showstopper for Ajax applications
- It will be fixed in IE7
Memory Leaks on IE6
- Remove all event handlers from deleted DOM nodes
- It must be done on nodes before removeChild or replaceChild
- It must be done on nodes before they are replaced by changing innerHTML
Breaking links in the DOM
function purgeEventHandlers(node) {
walkTheDOM(node, function(e) {
for (var n in e) {
if (typeof e[n] === 'function') {
e[n] = null;
}
}
});
}
Using our old friend walkTheDOM, we pass it this function. And what this function does, it will look at all the attributes, and if it finds any that look like functions, null them out. And if we call this on an object that we are gonna delete, this will take care of it.
As an alternative, you can use YUI, it has a purgeElement method that will do this for you.