PDA

View Full Version : [FIXED-1012] Ext.Button memory leak



bt_bruno
2 Jun 2010, 5:23 AM
Ext version tested:

Ext 3.2.1 rev 6683


Adapter used:

ext


css used:

only default ext-all.css


Browser versions tested against:

IE8


Operating System:

WinXP Pro


Description:


I'm doing some performance tests with my code, and I noticed a problem in Ext.Button class. The onRender method creates the button template, and then sign the button dom reference to an attribute called this.btnEl.


this.btnEl = btn.child(this.buttonSelector);

btn.child returns an Ext.Element reference, so the dom element is cached by Ext (Ext.elCache).

I guess that the problem is on this part of code, because when I comment it, and strip out all the parts that uses btnEl (almost all Ext.Button's code) the memory doesn't leak.

In onDestroy method you eliminate this.btnEl reference, but I guess the cached element remains on Ext.elCache.


onDestroy : function(){
if(this.rendered){
this.doc.un('mouseover', this.monitorMouseOver, this);
this.doc.un('mouseup', this.onMouseUp, this);
delete this.doc;
delete this.btnEl; //<-- the reference being eliminated
Ext.ButtonToggleMgr.unregister(this);
}
Ext.Button.superclass.onDestroy.call(this);
}


Test Case:

Basically I built a page with 2 functions and a global array. One function creates buttons and the other destroys. I monitore the memory usage on Window Task Manager for 1 minute. When everything is allright, the memory consume is constant, but when there's memory leaks, the memory only increases.

<html>
<head>
<link href="Include/extjs/css/ext-all.css" type="text/css" rel="stylesheet" />
<script type="text/javascript" src="Include/extjs/ext-base-debug.js"></script>
<script type="text/javascript" src="Include/extjs/ext-all-debug.js"></script>
<script type="text/javascript">

Ext.onReady(function()
{
var components = [];

window.setInterval(function(){

components.push( new Ext.Button({
iconCls : 'x-tbar-page-first',
disabled: true,
renderTo: document.body
}));

},100);

window.setInterval(function(){

var cmp = components.pop();

while(cmp)
{
cmp.destroy();
cmp = components.pop();
}

},5000);

});

</script>
</head>
<body>
</body>
</html>

The result that was expected:

Memory consume stays constant


The result that occurs instead:

The memory usage started on 1.63gb, and at the end of 1 minute it was on 1.69gb


Possible fix:
The beforeDestroy methods uses Ext.destroy to eliminate the repeater


Ext.destroy(this.repeater);

You could also destroy this.btnEl. In my case, this solved the leak and then when I re-ran the tests, everything was perfect.


Ext.override(Ext.Button,{

beforeDestroy : function(){
if(this.rendered){
this.clearTip();
}
if(this.menu && this.destroyMenu !== false) {
Ext.destroy(this.menu);
}
Ext.destroy(this.btnEl, this.repeater);
}

});

Jamie Avins
2 Jun 2010, 8:16 AM
Looks like an orphan, thanks for the report. We need to call destroy on the btnEl so we pull off the monitored events. Not such a good idea for us to use mon on an element, it's meant for components and this is what happens.