Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: .NET3.0 .NET3.5 Browser
After hosting WebBrowser control in WPF based application, it was observed that in repeated access to custom web pages the memory consumption keeps spiking and since this is a custom browser application so the WPF browser application goes into a hung state after some time.
 
I understand that the custom web page (being loaded) has badly written JavaScript resulting in memory leaks, So my question is, what are the ways in which we can bring down the memory consumption or stop it from hiking at first place.
 
One Solution is to clean the JavaScript as per the rules mentioned at Leak Patterns by Justin Rogers
 
What i was wondering was that, How can we implement some solution inside the Custom Web Browser based application to control the memory consumption of the Process?
 
Thanks in Advance,
Little Things
Posted 31-Jan-12 21:08pm
Edited 18-Feb-12 15:43pm
v3
Comments
SAKryukov at 1-Feb-12 2:15am
   
Why do you think there is a leak? If just by Task Manager, this is not a reliable result.
 
Badly written Javascript is not an excuse for memory leak. Web browser should tolerate any script, no matter what.
--SA
Little Things at 1-Feb-12 9:06am
   
Javascript Memory leak has been confirmed by using "Drip" a JavaScript Leak Detector

I tried a solution
IntPtr pHandle = GetCurrentProcess();
SetProcessWorkingSetSize(pHandle, -1, -1);
But it would bring down the WorkingSet, But the Privatebytes still keeps spiking until it reaches out of memory and the app crashes.

1 solution

Rate this: bad
good
Please Sign up or sign in to vote.

Solution 2

Since we might or might not have control over the web page loaded in our Web Browser control based application, so for the web pages
 
A) Code for those web pages on which we have control
B) Code for those web pages on which we don't have control
 

A) Code for those web pages on which we have control:
We will have to systematically implement points mentioned below. Following are the two points that should be taken care off while coding on client side
 
1)We can and should perform a clean up by implementing the rules mentioned in Leak Patterns by Justin Rogers
 
2)Bad JQuery programming technique can also bring the application to a halt and so there is a great solution that i felt should also be included in the clean up approach JQuery GarbageCollection
 

B) Code for those web pages on which we don't have control:
We will have to systematically implement a series of functions which should be called at Page UnLoad. Following are the two points that can be included in the
 
1) Event handling clean up manager method will keep track of all the added events and On unload, it can unregister all the handlers.
 
something like this
function ReleaseHandler() {
        var EvtMgr = (function() {
            var listenerMap = {};
 
            // Public interface
            return {
                addListener: function(evtName, node, handler) {
                    node["on" + evtName] = handler;
                    var eventList = listenerMap[evtName];
                    if (!eventList) {
                        eventList = listenerMap[evtName] = [];
                    }
                    eventList.push(node);
                },
 
                removeAllListeners: function() {
                    for (var evtName in listenerMap) {
                        var nodeList = listenerMap[evtName];
                        for (var i = 0, node; node = nodeList[i]; i++) {
                            node["on" + evtName] = null;
                        }
                    }
                }
            }
        })();
    }
 
2) For dereferencing function, the purge function will be passed a reference to a DOM element as an argument like this
purge(document.body)
It loops through the element's attributes. If it finds any functions, it nulls them out. This breaks the cycle, allowing memory to be reclaimed. It will also look at all of the element's descendent elements, and clear out all of their cycles as well. The purge function is harmless on Mozilla and Opera. It is essential on IE. The purge function should be called before removing any element, either by the removeChild method, or by setting the innerHTML property.
 
function purge(d){
var a = d.attributes, i, l, n;
if (a) {
for (i = a.length - 1; i >= 0 ; i -= 1) {
n = a[i].name;
if (typeof d[n] === 'function') {
d[n] = null;
}
}
}
a = d.childNodes;
if (a) {
l = a.length;
for (i = 0; i < l; i += 1) {
purge(d.childNodes[i]);
}
}
}
 
Note: The biggest reason for this Memory Leak in IE and IE based controls (Like Web Browser Control) is because there is a separate garbage collector for the DOM and for javascript.
  Permalink  
v3
Comments
AllenBerg at 6-Mar-13 13:47pm
   
I tried to implement this in my vb.net scraper app - i call the following code before nevagition to a new page, with the hopes that it will fix the memory leaks of the previous page.
 
code:
 

 
Public Shared Sub Clean_JS(ByRef wb As System.Windows.Forms.WebBrowser)
 
Dim args As Object() = {"document.body"}
 
Dim head As HtmlElement = wb.Document.GetElementsByTagName("head")(0)
 
Dim scriptEl0 As HtmlElement = wb.Document.CreateElement("script")
Dim element0 As mshtml.IHTMLScriptElement = DirectCast(scriptEl0.DomElement, mshtml.IHTMLScriptElement)
element0.text = "function ReleaseHandler() {" + vbCrLf + " var EvtMgr = (function() {" + vbCrLf + " var listenerMap = {};" + vbCrLf + " " + vbCrLf + " // Public interface" + vbCrLf + " return {" + vbCrLf + " addListener: function(evtName, node, handler) {" + vbCrLf + " node[""on"" + evtName] = handler;" + vbCrLf + " var eventList = listenerMap[evtName];" + vbCrLf + " if (!eventList) {" + vbCrLf + " eventList = listenerMap[evtName] = [];" + vbCrLf + " }" + vbCrLf + " eventList.push(node);" + vbCrLf + " }," + vbCrLf + " " + vbCrLf + " removeAllListeners: function() {" + vbCrLf + " for (var evtName in listenerMap) {" + vbCrLf + " var nodeList = listenerMap[evtName];" + vbCrLf + " for (var i = 0, node; node = nodeList[i]; i++) {" + vbCrLf + " node[""on"" + evtName] = null;" + vbCrLf + " }" + vbCrLf + " }" + vbCrLf + " }" + vbCrLf + " }" + vbCrLf + " })();" + vbCrLf + " }"
head.AppendChild(scriptEl0)
 
Dim scriptEl1 As HtmlElement = wb.Document.CreateElement("script")
Dim element1 As mshtml.IHTMLScriptElement = DirectCast(scriptEl1.DomElement, mshtml.IHTMLScriptElement)
element1.text = "function ReleaseHandler() {" + vbCrLf + " var EvtMgr = (function() {" + vbCrLf + " var listenerMap = {};" + vbCrLf + " " + vbCrLf + " // Public interface" + vbCrLf + " return {" + vbCrLf + " addListener: function(evtName, node, handler) {" + vbCrLf + " node[""on"" + evtName] = handler;" + vbCrLf + " var eventList = listenerMap[evtName];" + vbCrLf + " if (!eventList) {" + vbCrLf + " eventList = listenerMap[evtName] = [];" + vbCrLf + " }" + vbCrLf + " eventList.push(node);" + vbCrLf + " }," + vbCrLf + " " + vbCrLf + " removeAllListeners: function() {" + vbCrLf + " for (var evtName in listenerMap) {" + vbCrLf + " var nodeList = listenerMap[evtName];" + vbCrLf + " for (var i = 0, node; node = nodeList[i]; i++) {" + vbCrLf + " node[""on"" + evtName] = null;" + vbCrLf + " }" + vbCrLf + " }" + vbCrLf + " }" + vbCrLf + " }" + vbCrLf + " })();" + vbCrLf + " }"
head.AppendChild(scriptEl1)
 
wb.Document.InvokeScript("ReleaseHandler")
wb.Document.InvokeScript("purge", args)
 

End Sub
AllenBerg at 7-Mar-13 12:02pm
   
it appears that i am still leaking memory... does anyone see any issues with my vb.net code? am i interpreting the origial author correctly in my usage?
 
most of the 'code' here is actualy just assigning the javascript to a string... but that was copied off this site
Anshul Mehra at 7-Mar-13 21:17pm
   
Yes the memory would still be leaking because the above release handler fn() only takes care of Handlers with closure, something like this
 
element.onevent=function(){..}.
 
The original post and discussion thread for the same is at
Javascript memory leak cleanup in window unload

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
0 OriginalGriff 459
1 Maciej Los 325
2 Sergey Alexandrovich Kryukov 234
3 DamithSL 233
4 BillWoodruff 200
0 OriginalGriff 7,168
1 Sergey Alexandrovich Kryukov 6,377
2 DamithSL 5,461
3 Manas Bhardwaj 4,876
4 Maciej Los 4,450


Advertise | Privacy | Mobile
Web04 | 2.8.1411023.1 | Last Updated 7 Mar 2013
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100