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);
}
});
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);
}
});