admin管理员组文章数量:1327675
I am making an AJAX request for XML. I am doing this every second. I notice that my memory usage grows into the hundreds of megabytes. As you might imagine, the customer is not happy with this. After doing some reading in various places, I suspect that function closures are causing my headache. I am looking for any verification that can be had as well as any help for how to fix it.
function PageManager () {
var self = this;
self.timeoutHandler = function () {
$.ajax ({
url: 'URLtoXML',
type: 'post',
cache: false,
context: self,
success: function (data) {
var slf = this;
var xmlDoc = $($.parseXML (data));
xmlDoc.find ("tag_label").each (function () {
self.val = parseInt ($.trim ($(this).text ()));
}
setTimeout (slf.timeoutHandler, 750);
}
});
}
}
var pm = new PageManager ();
pm.timeoutHandler ();
EDIT I have incorporated some people's ideas and a little of the success handler internals. I see a smaller growth rate, but not by much.
I am making an AJAX request for XML. I am doing this every second. I notice that my memory usage grows into the hundreds of megabytes. As you might imagine, the customer is not happy with this. After doing some reading in various places, I suspect that function closures are causing my headache. I am looking for any verification that can be had as well as any help for how to fix it.
function PageManager () {
var self = this;
self.timeoutHandler = function () {
$.ajax ({
url: 'URLtoXML',
type: 'post',
cache: false,
context: self,
success: function (data) {
var slf = this;
var xmlDoc = $($.parseXML (data));
xmlDoc.find ("tag_label").each (function () {
self.val = parseInt ($.trim ($(this).text ()));
}
setTimeout (slf.timeoutHandler, 750);
}
});
}
}
var pm = new PageManager ();
pm.timeoutHandler ();
EDIT I have incorporated some people's ideas and a little of the success handler internals. I see a smaller growth rate, but not by much.
Share Improve this question edited Dec 1, 2011 at 21:52 Nik asked Dec 1, 2011 at 20:56 NikNik 7,28313 gold badges53 silver badges81 bronze badges 6-
@edit, have you tried my solution? It shouldn't cause an infinitely growing stack. I believe that any solution with
setTimeout
will, no matter how small your scope is. A smaller scope just means it grows slower. – Halcyon Commented Dec 1, 2011 at 21:27 - It looks like your suggestion has slowed the growth further. It's almost acceptable. I still don't see why I would have any growth. – Nik Commented Dec 1, 2011 at 21:36
- 1 People have been plaining about memoryleaks in jquery's XHR handling parts for years (at least 5, afaik), and in each new release they say "we fixed the memory leak" .. ehh ... just do the XHR manually. – tereško Commented Dec 1, 2011 at 21:36
- All browsers or specific to one? – Incognito Commented Dec 1, 2011 at 21:37
- 1 Does not seem to discriminate. – Nik Commented Dec 1, 2011 at 21:39
4 Answers
Reset to default 6To avoid that any newly created function (context) is closing over its parent scope here, you would just need to get rid of the anonymous function in setTimeout
there. So
setTimeout(self.timeoutHandler, 750);
However, even if that closure would clouse over the parent(s) contexts, any half decent garbage collector (like any modern browser have) will notice it and free the memory after the method has fired. The very important thing you didn't mention is on which browser you noticed the behavior. The Firefox garbage collector for instance, works .. pretty unpretictable (at least to me). It'll allow for more and more memory to get used and then on some point, it will release a huge chunk again.
To see what is going on, use Firefox and have a look into about:memory
while your script is running.
There you will see where the memory goes. I would not be worried if the memory usage increases for a while. Look at it, if that is all of your code, the memory should get freed sooner or later.
Memory grows when you keep references to things. It's a leak when you accidentally do this.
In this case your function timeoutHandler
calls itself, and again, and again ... It can never clean up the call stack. I'll bet this is your leak.
To avoid this problem use setInterval
. It works exactly like setTimeout
but it will keep calling the function every milliseconds until you clear it with clearTimeout
(or until the world ends).
The down side is that you can't time it very well, your current implementation always waits 750 milliseconds after each call. I suppose you could do something fancy that will still allow you time it well (using Date
to check the time), but it's not something I could write in 10 seconds :P
I'm just going to throw my two cents in but i agree jAndy (+1). However, I would generate a single bound callback once, rather than creating a new closure on ever iteration of the callback (which in theory could keep the scope and the xml data alive for a lot longer than you want. I would suggest another alternative like this:
function PageManager () {
var callback = (function(self) {
return function() { self.timeoutHandler(); };
})(this); // only one callback
this.timeoutHandler = function () {
$.ajax ({
url: '/echo/json/',
type: 'post',
cache: false,
data: {a:Math.random() },
success: function (data) {
//var xmlDoc = $($.parseXML (data));
// Processing of XML
//alert("data");
setTimeout (callback, 750);
}
});
};
}
var pm = new PageManager ();
pm.timeoutHandler();
Edit
Here is a jsFiddle with the above code, and I watched the memory management for a little while, but not nearly enough to be conclusive in any sense.
Your timeout function
setTimeout(self.timeoutHandler, 750);
may be causing memory leak. Although the success: callback is able to exit after finished, there may not be an empty context in a setTimeout callback causing a circular loop. Youl should take out the anonymous function to end up something like this:
var pManager = new PageManager ();
pManager.timeoutHandler();
function PageManager () {
var ret = (function(self) {
return function() { self.timeoutHandler(); };
})(this);
this.timeoutHandler = function () {
$.ajax ({
url: '/echo/json/',
type: 'post',
cache: false,
success: function (data) {
setTimeout (ret, 750);
}
});
};
}
This should only call back once.
本文标签: javascriptjQuery Memory Leak SuspicionStack Overflow
版权声明:本文标题:javascript - jQuery Memory Leak Suspicion - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742223803a2435638.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论