PDA

View Full Version : [OPEN-1331] Extjs.Ajax (3.2.2) Leak



wsi
12 Oct 2010, 7:45 AM
ExtJs version: 3.2.2

Overview:

I have a Javascript file that sends an AJAX request out to a server which hosts a PHP script that returns a random number. The returned AJAX value is written to a text field in a form and then the same request is sent to the server again. This process continues indefinitely.

Issue: Web browser Memory usage is constantly increasing.

Test results:

Oct 8, 2010 at 4:03PM memory usage reported by Windows Task Manager

FF: 27 016K
Chrome: 15 616K
IE 8: 26 368K


Oct 12, 2010 at 8:36AM memory usage reported by Windows Task Manager

FF: 64 220K
Chrome: 49 304K
IE 8: 47 268K


As of recording the 8:36AM, memory usage has increased slightly.


Tested Browsers: IE 8.0.7600.16385, Chrome 6.0.472.63, Firefox 3.6.10


PHP source code:


<?php

sleep(1);
echo "response ".time();

?>
HTML + JAVASCRIPT source:




<html>

<head>

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

</head>

<body>

<script type="text/javascript">

Ext.onReady(function(){

var simple = new Ext.FormPanel({
labelWidth: 75, // label settings here cascade unless overridden
url:'save-form.php',
frame:true,
title: 'Simple Form',
bodyStyle:'padding:5px 5px 0',
width: 350,
defaults: {width: 230},
defaultType: 'textfield',

items: [
{
id: 'response_field',
fieldLabel: 'response',
name: 'response'
}
]
});

simple.render(document.body);



function makeRequest(){

Ext.Ajax.request({
url: 'router.php',
success: function(response, opts){

Ext.getCmp('response_field').setValue(response.responseText);
makeRequest();

},
failure: function(){
makeRequest();
},
params: {
foo: 'bar'
}
});

}

makeRequest();


});



</script>


</body>
</html>


Comment:

Is this a leak in the framework or is there something I can do to prevent the browser memory usage from constantly increasing?

jsakalos
12 Oct 2010, 10:38 AM
Only one thing comes to my mind:

Try to not define failure and success functions inline - remove them to vars. If it doesn't help I can move this thread to bugs for the devel team to investigate the matter.

wsi
14 Oct 2010, 11:24 AM
I modified the javascript to not use inline failure and success functions. The modified code is:




<html>

<head>

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

</head>

<body>


<script type="text/javascript">

Ext.onReady(function(){

var simple = new Ext.FormPanel({
labelWidth: 75, // label settings here cascade unless overridden
url:'save-form.php',
frame:true,
title: 'Simple Form',
bodyStyle:'padding:5px 5px 0',
width: 350,
defaults: {width: 230},
defaultType: 'textfield',

items: [
{
id: 'response_field',
fieldLabel: 'response',
name: 'response'
}
]
});

simple.render(document.body);

var success_handler = function(response, opts){
Ext.getCmp('response_field').setValue(response.responseText);
makeRequest();
};

var failure_handler = function(){
makeRequest();
};


function makeRequest(){

Ext.Ajax.request({
url: 'router.php',
success: success_handler,
failure: failure_handler,
params: {
foo: 'bar'
}
});
}

makeRequest();

});



</script>


</body>
</html>





The test results are as follows


Oct 13, 2010 @ 2:49PM

chrome: 33 656K

ff: 43 092K

ie 8: 40 598K


----------------------------


Oct 13, 2010 @ 4:44PM

chrome: 42 708K

ff: 58, 552K

IE 8: 40, 596K


----------------------------

Oct 14, 2010 @ 1:15PM

Chrome: 55 192K

FF: 62 664K

IE 8: 45 132K


The leak still exists.

jsakalos
14 Oct 2010, 11:28 AM
OK, moving this thread to bugs for the devel team to fix/comment/explain.

jay@moduscreate.com
14 Oct 2010, 11:35 AM
to be honest, your test case is flawed. You should *NOT* be rendering items to the DOM when testing utilities such as Ext.Ajax.

wsi
14 Oct 2010, 12:10 PM
I am a little confused about your comment; can you direct me to the line of code that renders items to the DOM? I am making a guess that you are referring to the line.


Ext.getCmp('response_field').setValue(response.responseText); If that line is causing the issue, would the following modification fix the issue?




<html>

<head>

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

</head>

<body>

<script type="text/javascript">

Ext.onReady(function(){

var single_text_field = new Ext.form.TextField({
fieldLabel: 'response',
name: 'response'
});

var simple = new Ext.FormPanel({
labelWidth: 75, // label settings here cascade unless overridden
frame:true,
title: 'Simple Form',
bodyStyle:'padding:5px 5px 0',
width: 350,
defaults: {width: 230},
defaultType: 'textfield',
items: [
single_text_field
]
});

simple.render(document.body);

var success_handler = function(response, opts){
single_text_field.setValue(response.responseText);
makeRequest();
};

var failure_handler = function(){
makeRequest();
};


function makeRequest(){

Ext.Ajax.request({
url: 'router.php',
success: success_handler,
failure: failure_handler,
params: {
foo: 'bar'
}
});
}

makeRequest();

});



</script>


</body>
</html>

jay@moduscreate.com
14 Oct 2010, 12:13 PM
http://tdg-i.com/img/screencasts/2010-10-14_1613.png

jay@moduscreate.com
14 Oct 2010, 12:14 PM
Also, how are you testing this? Are you refreshing the page?! If so, you're doing it wrong (again).

nm i get it.

VinylFox
14 Oct 2010, 12:20 PM
Simply put, Jay is saying that your example has both a Form and the Ajax request, so there is no way to know which is causing the memory leak.

Might be the form, field, layout, getCmp, setValue, etc, etc, etc.

Just make it simpler and test again. ie:


var success_handler = function(response, opts){
makeRequest();
};

var failure_handler = function(){
makeRequest();
};

function makeRequest(){

Ext.Ajax.request({
url: 'router.php',
success: success_handler,
failure: failure_handler,
params: {
foo: 'bar'
}
});
}

makeRequest();

jay@moduscreate.com
14 Oct 2010, 12:23 PM
Thx Shea.

I'm bouncing around a lot today (too much to do ++ too much caffeine :().

jay@moduscreate.com
14 Oct 2010, 12:27 PM
FWIW, the *leanest* code (does not recreate strings, objects, etc);




var success_handler = function(response, opts){
makeRequest();
},
failure_handler = function(){
makeRequest();
},
ajaxCfg = {
url: 'router.php',
success: success_handler,
failure: failure_handler,
params: {
foo: 'bar'
}
};


function makeRequest(){
Ext.Ajax.request(ajaxCfg);
}

makeRequest();

jay@moduscreate.com
14 Oct 2010, 12:30 PM
He only sets value - I would expect that that cannot/shouldn't cause the leak.
DOM manipulation is one of the leading causes of memory leaks, IMHO. each browser acts differently.

meroy
15 Oct 2010, 1:56 PM
This has been entered into Trac. Thanks!

wsi
15 Oct 2010, 2:15 PM
Thank you, what is Trac?

Condor
18 Oct 2010, 12:12 AM
Trac is the issue tracker used internally by the Sencha team.

Reimius
29 Mar 2012, 6:40 AM
Sorry to respond to such an old thread, but this leak is still apparent in Ext 4.0.7 even. I have tested it on IE9 and it seems that the test case will leak more if you return a larger dataset from the server. The odd thing is that the current version of Google Chrome does not leak. With my test case I have also noticed that the memory does hit a ceiling and then stop (but I'm not sure why). I have been using Drip to test the explorer leak after reports of our actually application crashing browsers.33306
The only difference between my test cases with 4.0.7 and 3.2.1 is that 4.0.7 takes about 3x longer to get to the same ceiling. I can provide my test cases if that will help.

And just so you know, the ceiling it hits is not reasonable for our actual user base, it's about 1.7 Gb

Reimius
29 Mar 2012, 7:27 AM
Hello again,

According to my research and testing, the issue is with this code in the Ext Base in 3.2.1:

function handleReadyState(o, callback){ callback = callback || {};
var conn = o.conn,
tId = o.tId,
poll = pub.poll,
cbTimeout = callback.timeout || null;


if (cbTimeout) {
pub.conn[tId] = conn;
pub.timeout[tId] = setTimeout(function() {
pub.abort(o, callback, true);
}, cbTimeout);
}


poll[tId] = setInterval(
function() {
if (conn && conn.readyState == 4) {
clearInterval(poll[tId]);
poll[tId] = null;


if (cbTimeout) {
clearTimeout(pub.timeout[tId]);
pub.timeout[tId] = null;
}


handleTransactionResponse(o, callback);
}
},
pub.pollInterval);
}

the variable conn should not be referenced within the onreadystatechange, and 'this' should be used instead. There are also other variables being used from the outer scope and I'm not sure how to handle those, but according to the section: XmlHttpRequest memory management and leaks on this page: "http://javascript.info/tutorial/memory-leaks#ie-lt-8-dom-js-memory-leak" this code will cause a memory leak. And I have tested from within my app to verify that it happens.

Since 4.0.7 also leaks in the same manner, I assume this code has been carried over, or is still similar. I'm also surprised that more people haven't had this problem.

Reimius
29 Mar 2012, 7:57 AM
Actually, after more review of the code, I'm not sure if my last post makes sense, but I'm going to leave it there because I believe the issue is still around that code area.

Reimius
10 May 2012, 1:39 PM
I saw this thread again today... fyi, the source of the problem (or one of the sources, or part of the problem) is the way Extjs decodes json (which is used in the ajax call). It uses the eval function which is known to cause memory leaks when used. To work around this I used jQuery's ajax call (which is the only framework I could find that didn't leak in all browsers) and json_parse from https://github.com/douglascrockford/JSON-js/blob/master/json_parse.js which does not use eval to avoid memory leaks. Just posting this to help others in the same situation as I, and maybe to help the Ext with their own solution to this problem.

dracofyre
31 Oct 2012, 4:20 AM
Any more information on this topic?