PDA

View Full Version : setTimeout, closures, and memory leak help



WA
Mar 10th, 2007, 06:13 AM
Hi:
I'm trying to understand how to resolve an IE memory leak that occurs in the following general situation. Basically, if I use a closure inside setTimeout() to call an object instance method repeatedly, in which the method accesses the .innerHTML property of an element to modify it's HTML, a leak occurs in IE. For example:



<div id="numberdiv">holder</div>
<script type="text/javascript">
function timemachine(offset){
this.offset=offset
this.display()
}
timemachine.prototype.display=function(){
//Use the innerHTML property to assign rich HTML to an element, in combo with closure- leak in IE!
document.getElementById("numberdiv").innerHTML='<p><b>'+this.offset+new Date().getSeconds()+'</b></p>'
var _this=this
//Closure below, no leak by itself
setTimeout(function(){_this.display()}, 1000)
}
var sample=new timemachine(5)
</script>


I've tried a few standard techniques to plugging the leak, but nothing has worked. Anyone know of an elegant solution that doesn't require "re-wiring" everything?

MikeFoster
Mar 11th, 2007, 08:02 PM
Hi WA,

I may be wrong about this, but I think the mem leak is so noticeable because a new closure is created each time 'display' is called. So an idea is to use a technique that only requires one closure. For example:



<!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>Template</title>
<style type='text/css'>
</style>
<script type='text/javascript'>
window.onload = function()
{
window.sample1 = new timeMachine(5, 'numberDiv1');
window.sample2 = new timeMachine(-6, 'numberDiv2');
}
function timeMachine(offset, id)
{
// Public
this.offset = offset;
this.id = id;
// Private
var _this = this;
function display()
{
// Use '_this' here, not 'this'.
document.getElementById(_this.id).innerHTML = '<p><b>' + (_this.offset + new Date().getSeconds()) + '</b></p>';
// Instead of multiple closures on 'display', we now have only one closure on 'timeMachine'.
setTimeout(display, 1000);
}
// Constructor Code
display();
}
</script>
</head>
<body>

<div id="numberDiv1">holder</div>
<div id="numberDiv2">holder</div>

</body>
</html>

WA
Mar 12th, 2007, 08:29 AM
Thanks for the suggestion. I gave your code a test run, though in Drip, it still shows the same leak occurring with the P and B tags that are getting dynamically added via .innerHTML. I'm using Drip 0.5 btw. I did receive some further help from someone who suspect that Drip itself may be faulty, and sometimes will misdiagnose memory leaks. He concluded this after testing out the above code, and not seeing any actual memory leaks when viewing "task manager", while in Drip, it does report memory being consumed incrementally.