PDA

View Full Version : [UPDATED] Destroying DOM Nodes and Memory Usage



Zac
12 Jun 2007, 5:25 PM
6/14 - Completely rewrote this thread because the old version was too complicated to show the issue easily.

Ext leaks DOM elements in IE. This has a big effect on performance after multiple widgets are created and destroyed.

Steps to Reproduce:

Download sIEve @ http://home.orange.nl/jsrosman/
Take the Hello World dialog example and add in a new button in the .html.
Hook a click event up to that button in the .js and use it to call dialog.destroy(true) (Code below to make it quicker.)
Load the document in sIEve.
Click the 'Hello World' button. Memory and # of DOM nodes will increase.
Click the button you created. Notice changes to memory and # of nodes.
Click on the 'Show In Use' button and look for Yes in the Orphan column.



In the Hello World example above it removes 19 of the 68 DOM nodes created correctly. Most of the leftovers are orphans that IE can't remove because they are still referenced somewhere in the JS and vice-versa.


This is a problem with desktop-style applications that are expected to run all day without crashing. There's no way I'd be comfortable convincing my boss to let me use Ext for a project knowing this would be a big problem down the road.

You can blame IE for this...but realize that almost all of the big companies are locked into using it.

hello.html


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Hello World Dialog Example</title>
<link rel="stylesheet" type="text/css" href="../../resources/css/ext-all.css" />

<!-- GC --> <!-- LIBS -->
<script type="text/javascript" src="../../adapter/yui/yui-utilities.js"></script>
<script type="text/javascript" src="../../adapter/yui/ext-yui-adapter.js"></script>
<!-- ENDLIBS -->

<script type="text/javascript" src="../../ext-all.js"></script>

<script language="javascript" src="hello.js"></script>

<!-- Common Styles for the examples -->
<link rel="stylesheet" type="text/css" href="../examples.css" />
</head>
<body>
<script type="text/javascript" src="../examples.js"></script><!-- EXAMPLES -->

<h1>Hello World Dialog</h1>
<p>This example shows how to create a very simple modal BasicDialog with "autoTabs".</p>
<input type="button" id="show-dialog-btn" value="Hello World" /><br /><br />
<input type="button" id="close-dialog-btn" value="Goodbye World" /><br /><br />

<p>Note that the js is not minified so it is readable. See <a href="hello.js">hellos.js</a> for the full source code.</p>
Here's snapshot of the code that creates the dialog:
<pre class="code"><code>dialog = new Ext.BasicDialog("hello-dlg", {
modal:true,
autoTabs:true,
width:500,
height:300,
shadow:true,
minWidth:300,
minHeight:300
});
dialog.addKeyListener(27, dialog.hide, dialog);
dialog.addButton('Close', dialog.hide, dialog);
dialog.addButton('Submit', dialog.hide, dialog).disable();
</code></pre>

<!-- The dialog is created from existing markup.
The inline styles just hide it until it created and should be in a stylesheet -->
<div id="hello-dlg" style="visibility:hidden;position:absolute;top:0px;">
<div class="x-dlg-hd">Hello Dialog</div>
<div class="x-dlg-bd">
<!-- Auto create tab 1 -->
<div class="x-dlg-tab" title="Hello World 1">
<!-- Nested "inner-tab" to safely add padding -->
<div class="inner-tab">
Hello...<br><br><br>
</div>
</div>
<!-- Auto create tab 2 -->
<div class="x-dlg-tab" title="Hello World 2">
<div class="inner-tab">
... World!
</div>
</div>
</div>
</div>
</div>
</body>
</html>


hello.js


/*
* Ext JS Library 1.1 Beta 1
* Copyright(c) 2006-2007, Ext JS, LLC.
* licensing@extjs.com
*
* http://www.extjs.com/license
*/

// create the HelloWorld application (single instance)
var HelloWorld = function(){
// everything in this space is private and only accessible in the HelloWorld block

// define some private variables
var dialog, showBtn, hideBtn;

// return a public interface
return {
init : function(){
showBtn = Ext.get('show-dialog-btn');
// attach to click event
showBtn.on('click', this.showDialog, this);

hideBtn = Ext.get('close-dialog-btn');
hideBtn.on('click', this.closeDialog, this);

},

showDialog : function(){
if(!dialog){ // lazy initialize the dialog and only create it once
dialog = new Ext.BasicDialog("hello-dlg", {
autoTabs:true,
width:500,
height:300,
shadow:true,
minWidth:300,
minHeight:250,
proxyDrag: true
});
dialog.addKeyListener(27, dialog.hide, dialog);
dialog.addButton('Submit', dialog.hide, dialog).disable();
dialog.addButton('Close', dialog.hide, dialog);
}
dialog.show(showBtn.dom);
},

closeDialog : function(dlg) {
dialog.destroy(true);
delete dialog;
}
};
}();

// using onDocumentReady instead of window.onload initializes the application
// when the DOM is ready, without waiting for images and other resources to load
Ext.onReady(HelloWorld.init, HelloWorld, true);

Zac
14 Jun 2007, 4:33 PM
ttt - rewrote the post above.

JohnRaab
7 Sep 2007, 4:49 AM
Yes we are having the same problem. Works fine in FireFox, but IE leaks memory when using dialog.destroy(true). I've been trying to find a way to use Ext Dialogs and have them cleanup after themselves in IE to no avail.

JohnRaab
7 Sep 2007, 5:22 AM
I don't think these are actually leaks, but instead IE doing internal caching. sIEve does not report any actual leaks. After opening/closing(and destroying) popins to get IE up to 200mb usage, if I go to about:blank and return its down to 55mb, and further browsing got it down to 40mb.

mystix
7 Sep 2007, 11:06 AM
if you checked in FF, and all DOM nodes / listeners are being destroyed correctly, then
it's an IE pseudo-leak i.e. memory usage goes up, but no DOM / js leakage occurs.

see this thread for more info:
http://extjs.com/forum/showthread.php?t=11810&highlight=pseudo