JavaScript memory management question
I'm working on an embedded product which uses a WebKit-based browser, and I've been tracking down some memory leaks we're seeing. After a long while of digging through the codebase, I've been able to determine that we're occasionally leaking the WebCore::Document object when leaving certain websites. A bit more tracing reveals that the Document object is being retained because an HTMLImageElement holds a DocPtr reference on it, and the element isn't going away when the normal refcount on the Document drops to 0. This pins the Document object in memory. The specific site I've been testing with is www.yahoo.com. Examining the source code to that page reveals the following in the page's beforeUnload event: window.onbeforeunload=function(){ var img=new Image; now=new Date; t6=now.getTime(); img.src=' http://www.yahoo.com/'+(ylp?ylp:'p.gif?t=0')+cc+'&tid='+ver+'&ni='+document.images.length+'&sss='+sss+'&t1='+t1+'&d1='+(t2-t1)+'&d2='+(t3-t1)+'&d3='+(t4-t1)+'&d4='+(t5-t1)+'&d5='+(t6-t1)+'&d6='+(t7-t1)+'&d7='+(t8-t1)+'&d8='+(t9-t1)+'&d9='+(t10-t1)+'&d10='+(t11-t1)+'&d11='+(t12-t1); } It appears that this Image object is never being removed--I can repeatedly navigate to and from this site and watch HTMLImageElements (and their associated Document objects) pile up. I'm still not convinced this is a WebKit problem specifically (there's a fair amount of code surrounding it in our product that could potentially have bugs in it), but to continue tracing the problem, I need to know what the mechanism is that *ought* to be freeing this object. I presume this is something that should be taken care of by the JavaScript garbage collector, however I can see JavaScriptCore::Collector::collect() calls running occasionally after this object is created, and it never goes away. Is there some immediately apparent reason why this wouldn't be happening? I.e., is there something else that would be holding a reference to an object created by this type of script code, or is something other than the GC responsible for freeing it, etc? My apologies if this turns out to be a stupid question--I'm just trying to get some context for where I ought to focus next. Thanks, Matt
On Dec 4, 2008, at 12:55 PM, Matt Fischer wrote:
I'm working on an embedded product which uses a WebKit-based browser, and I've been tracking down some memory leaks we're seeing. After a long while of digging through the codebase, I've been able to determine that we're occasionally leaking the WebCore::Document object when leaving certain websites. A bit more tracing reveals that the Document object is being retained because an HTMLImageElement holds a DocPtr reference on it, and the element isn't going away when the normal refcount on the Document drops to 0. This pins the Document object in memory.
The specific site I've been testing with is www.yahoo.com. Examining the source code to that page reveals the following in the page's beforeUnload event:
window.onbeforeunload=function(){ var img=new Image; now=new Date; t6=now.getTime(); img.src='http://www.yahoo.com/'+(ylp?ylp:'p.gif?t=0')+cc+'&tid='+ver +'&ni='+document.images.length+'&sss='+sss+'&t1='+t1+'&d1='+(t2- t1)+'&d2='+(t3-t1)+'&d3='+(t4-t1)+'&d4='+(t5-t1)+'&d5='+(t6-t1) +'&d6='+(t7-t1)+'&d7='+(t8-t1)+'&d8='+(t9-t1)+'&d9='+(t10- t1)+'&d10='+(t11-t1)+'&d11='+(t12-t1); }
It appears that this Image object is never being removed--I can repeatedly navigate to and from this site and watch HTMLImageElements (and their associated Document objects) pile up.
I'm still not convinced this is a WebKit problem specifically (there's a fair amount of code surrounding it in our product that could potentially have bugs in it), but to continue tracing the problem, I need to know what the mechanism is that *ought* to be freeing this object. I presume this is something that should be taken care of by the JavaScript garbage collector, however I can see JavaScriptCore::Collector::collect() calls running occasionally after this object is created, and it never goes away. Is there some immediately apparent reason why this wouldn't be happening? I.e., is there something else that would be holding a reference to an object created by this type of script code, or is something other than the GC responsible for freeing it, etc?
My apologies if this turns out to be a stupid question--I'm just trying to get some context for where I ought to focus next.
Have you tried it on WebKit trunk? I think this this is fixed by r37922. - Maciej
On Thu, Dec 4, 2008 at 3:06 PM, Maciej Stachowiak <mjs@apple.com> wrote:
On Dec 4, 2008, at 12:55 PM, Matt Fischer wrote:
I'm working on an embedded product which uses a WebKit-based browser, and I've been tracking down some memory leaks we're seeing. After a long while of digging through the codebase, I've been able to determine that we're occasionally leaking the WebCore::Document object when leaving certain websites. A bit more tracing reveals that the Document object is being retained because an HTMLImageElement holds a DocPtr reference on it, and the element isn't going away when the normal refcount on the Document drops to 0. This pins the Document object in memory.
The specific site I've been testing with is www.yahoo.com. Examining the source code to that page reveals the following in the page's beforeUnload event:
window.onbeforeunload=function(){ var img=new Image; now=new Date; t6=now.getTime(); img.src=' http://www.yahoo.com/'+(ylp?ylp:'p.gif?t=0')+cc+'&tid='+ver+'&ni='+document.images.length+'&sss='+sss+'&t1='+t1+'&d1='+(t2-t1)+'&d2='+(t3-t1)+'&d3='+(t4-t1)+'&d4='+(t5-t1)+'&d5='+(t6-t1)<http://www.yahoo.com/%27+%28ylp?ylp:%27p.gif?t=0%27%29+cc+%27&tid=%27+ver+%27&ni=%27+document.images.length+%27&sss=%27+sss+%27&t1=%27+t1+%27&d1=%27+%28t2-t1%29+%27&d2=%27+%28t3-t1%29+%27&d3=%27+%28t4-t1%29+%27&d4=%27+%28t5-t1%29+%27&d5=%27+%28t6-t1%29>+'&d6='+(t7-t1)+'&d7='+(t8-t1)+'&d8='+(t9-t1)+'&d9='+(t10-t1)+'&d10='+(t11-t1)+'&d11='+(t12-t1); }
It appears that this Image object is never being removed--I can repeatedly navigate to and from this site and watch HTMLImageElements (and their associated Document objects) pile up.
I'm still not convinced this is a WebKit problem specifically (there's a fair amount of code surrounding it in our product that could potentially have bugs in it), but to continue tracing the problem, I need to know what the mechanism is that *ought* to be freeing this object. I presume this is something that should be taken care of by the JavaScript garbage collector, however I can see JavaScriptCore::Collector::collect() calls running occasionally after this object is created, and it never goes away. Is there some immediately apparent reason why this wouldn't be happening? I.e., is there something else that would be holding a reference to an object created by this type of script code, or is something other than the GC responsible for freeing it, etc?
My apologies if this turns out to be a stupid question--I'm just trying to get some context for where I ought to focus next.
Have you tried it on WebKit trunk? I think this this is fixed by r37922.
- Maciej
Sadly, I'm stuck on a rather ancient version of WebKit (circa October 2007), with little hope of pulling up substantially, due to all the API breaks combined with our project's timeframe. :( Is there, by chance, any simple change I could make which would emulate this fix on a snapshot that old? It's from before the days of WebCore::ScriptController and WebCore::JSDOMWindowShell, which appear to be the pertinent classes to this patch. I tried a couple naive attempts to backport it, such as calling clear() on the Window object that was getting its disconnectFrame() called in the Frame::pageDestroyed() function. This didn't seem to have any effect, but I admittedly had close to zero understanding of what I was doing there. --Matt
participants (2)
-
Maciej Stachowiak
-
Matt Fischer