473,573 Members | 3,331 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

more details on jscript memory leak from DOM object references

About a month ago Richard Cornford did an interesting analysis of a
memory leak
in jscript (internet explorer) when there are "circular" references
between
DOM objects and (real) jscript objects:

http://groups.google.com/groups?selm...ws.demon.co.uk

This message summarizes some testing I've done and their results.
These results somewhat contradict Cornford's conclusions; I haven't
analyzed his
test page to come to an explanation.

Below is an html test page so that anyone can (attempt to) reproduce
my results.
To test:
- Bring up task manager and a fresh IE process on this web page.
- Click on one of the div links, refresh the page, repeat, and watch
the process size.
I have been doing 3 refresh/click sequences per div.

Because the leaked object is at least 1Mbyte, it should be apparent
when the leak happens.
(I see leaks in increments of 2Mbyte, presumably because the
characters
in the 10^6 long string are stored as 2 bytes each, for unicode.)

I did my testing on IE 6.0.
I also ran the tests on Mozilla 1.1. I discovered that the largeText
function
is much slower to execute on Mozilla than IE, but I found no leaks.

question: Does the leak occur if an event handler function refers to
only global js objects?
test: leak_test_globa l
answer: No.
Apparently references to global variables (scope "window") are not
implemented in
the same way as lexical closures on local variables.

question: Does the leak happen if an event handler function refers to
a local js object?
test: leak_test_local
answer: Yes.

question: Does the leak happen without true circularity, just mutual
references somewhere between DOM and JS?
test: leak_test_2node s
answer: Yes (true circularity is not required).

question: Does the leak occur with just a one-way reference from a DOM
object to a JS object?
test: leak_test_domre f
answer: Yes (not even mutual reference is required).

question: Does the leak occur with just a one-way reference from a JS
object to a DOM object?
test: leak_test_jsref
answer: No.

question: Are all JS objects leaked which are reachable by transitive
reference from one bound by lexical closure?
test: leak_test_reach able
answer: Yes.

question: Does Node.attachEven t also leak?
test: leak_test_attac hEvent
answer: Yes

-mda

------- testleak.html -----
<html>
<!-- Tests of internet explorer leaks. See discussion in
comp.lang.javas cript, 2003-7-24 -->
<head>
<script type="text/javascript">
function largeText(len, s) {
if (!s) s = '0123456789';
var a = [];
for(var i=len/s.length;i--;) a.push(s);
return a.join('');
}

var myglobal = [];
myglobal.big = largeText(10000 00, largeText(1000) );
//alert("myglobal .big.length=" + myglobal.big.le ngth);

function test_start(name ) {
alert("performi ng test '" + name + "'");
}

function leak_test_globa l(node) {
test_start('glo bal');
node.onclick = function() {alert("length: " + myglobal.length )};
myglobal.push(n ode); // make circular
}

function leak_test_local (node) {
test_start('loc al');
var mylocal = myglobal;
node.onclick = function() {alert("length: " + mylocal.length) };
mylocal.push(no de);
}

function leak_test_2node s(node) {
test_start('2no des');
var mylocal = myglobal;
var node2 = document.create Element('div');
document.body.a ppendChild(node 2);
node.onclick = function() {alert("length: " + mylocal.length) };
mylocal.push(no de2);
}

function leak_test_domre f(node) {
test_start('dom ref');
var mylocal = myglobal;
node.onclick = function() {alert("length: " + mylocal.length) };
}

function leak_test_jsref (node) {
test_start('jsr ef');
myglobal['foobar'] = node;
}

function leak_test_reach able(node) {
test_start('rea chable');
var mylocal = {stuff : {bother: myglobal}};
node.onclick = function() {alert("length: " +
mylocal.stuff.b other.length)};
mylocal['mynode'] = node;
}

function leak_test_attac hEvent(node) {
test_start('att achEvent');
if (!node.attachEv ent) {alert("no attachEvent"); return;}
var mylocal = myglobal;
node.attachEven t('onclick', function() {alert("length: " +
mylocal.length) });
// reference seems unnecessary
//mylocal.push(no de);
}
</script>
</head>
<body>

<div onclick="leak_t est_global(this )">leak_test_gl obal (expect:
PASS)</div>
<div onclick="leak_t est_local(this) ">leak_test_loc al (expect:
FAIL)</div>
<div onclick="leak_t est_2nodes(this )">leak_test_2n odes (expect:
FAIL)</div>
<div onclick="leak_t est_domref(this )">leak_test_do mref (expect:
FAIL)</div>
<div onclick="leak_t est_jsref(this) ">leak_test_jsr ef (expect:
PASS)</div>
<div onclick="leak_t est_reachable(t his)">leak_test _reachable (expect:
FAIL)</div>
<div onclick="leak_t est_attachEvent (this)">leak_te st_attachEvent
(expect: FAIL)</div>
<br>
<div onclick="Collec tGarbage()">Col lectGarbage (expect: never does
anything)</div>
</body>
</html>
Jul 20 '05 #1
4 5540
"Mark D. Anderson" <md*@discerning .com> wrote in message
news:b9******** *************** ***@posting.goo gle.com...
About a month ago Richard Cornford did an interesting
analysis of a memory leak
in jscript (internet explorer) when there are "circular"
references between DOM objects and (real) jscript objects:
<snip URL of previous discussion via groups.google.c om>
This message summarizes some testing I've done and their
results. These results somewhat contradict Cornford's
conclusions; I haven't analyzed his test page to
come to an explanation.

Below is an html test page so that anyone can (attempt
to) reproduce my results. To test:
- Bring up task manager and a fresh IE process on this
web page.
- Click on one of the div links, refresh the page, repeat,
and watch the process size.
I have been doing 3 refresh/click sequences per div.


I am not going to have time to examine your test page in detail tonight
(and maybe not tomorrow either) to see if and why you think your results
are different to mine (if you are going to claim your results contradict
my conclusions it would have saved a bit of time if you had stated the
specific conclusions that you think are contradicted). I should be able
to find time to look at your page in detail over the weekend and let you
know what I think.

However, did you notice early in the previous thread Jim Ley implying
that just repeatedly refreshing the same page may give the impression of
a memory leak in IE when navigating away from the page would free the
memory. He specifically agreed with my suggestion that any page wishing
to demonstrate a real problem in IE would have to cycle between at least
two distinct pages.

While I would not take anyone's word as gospel, when it comes to
obscurer details of browser behaviour I would always pay close attention
to what Jim has to say. Accordingly my tests used two or three pages and
cycled between them. As a result I am certain that they do demonstrate
the memory leaks I described, though I may have concluded that the
problem was more general than it actually is. But I will be
incorporating your code into Multi-page examples for testing.

Giving your script a cursory glance, specifically the -
leak_test_globa l - function, I don't think that it demonstrates that
references to global objects do not produce leaks as the DIV element
does not have a reference to the global object and the closure formed by
assigning the event handling function does not contain a reference to
the global object. If you replace the event handling function with an
expando property that refers to the global object, so that the reference
is circular:-

function leak_test_globa l(node) {
test_start('glo bal');
node.expando1 = myglobal;
myglobal.push(n ode); // make circular
}

- I think you will find that it does leak.

Richard.
Jul 20 '05 #2
"Mark D. Anderson" <md*@discerning .com> wrote in message
news:b9******** *************** ***@posting.goo gle.com...
<snip>
question: Does the leak occur with just a one-way
reference from a DOM object to a JS object?
test: leak_test_domre f
answer: Yes (not even mutual reference is required). <snip>function leak_test_domre f(node) {
test_start('dom ref');
var mylocal = myglobal;
node.onclick = function() {
alert("length: " + mylocal.length) };
}

<snip>

I am getting hooked (and I should be sleeping). This one is not a
one-way reference. Assigning the inner function to onclick is forming a
closure. That closure creates a circular reference becase its - node -
parameter is a reference to the DIV and the DIV has a reference to the
inner function. Those circular references preserve the closure and the
closure contains a reference to - myglobal -, preserving it. Try nulling
the - node - reference at the end of the function; breaking the circle.

function leak_test_domre f(node) {
test_start('dom ref');
var mylocal = myglobal;
node.onclick = function() {
alert("length: " + mylocal.length) };
node = null;
}

leak_test_reach able - and - leak_test_attac hEvent - have similar
problems.

Richard.
Jul 20 '05 #3
"Mark D. Anderson" <md*@discerning .com> wrote in message
news:b9******** *************** ***@posting.goo gle.com...
FYI I have a new version at
http://www.discerning.com/js/testleak.html with corrections
reflecting your comments, some additions, and general cleanup.
Would you mind removing my e-mail address from that page. As I never
respond to unsolicited e-mail from total strangers it can server no
purpose but encourage spam.
(if you are going to claim your results contradict my
conclusions it would have saved a bit of time if you had stated
the specific conclusions that you think are contradicted).


Sorry. But now with your corrections, I'm not sure there are
contradictio ns anymore :).


Yes, I do not see anything that contradicts my original conclusions.
Circular references between DOM elements and JS objects do prevent
garbage collection on IE and one-way references do not.
I should say too that I started with your posting not to pick
on you, but because it was the best I found anywhere.
I didn't think that you did, and I am not arrogant enough to think that
I could not have been wrong in the first place. I just would have liked
to be able to narrow down to the specifics quickly.

<snip>Btw, i'm guessing that CollectGarbage( ) on IE does something
similar to what navigating to a new site would do;
neither seems to have any consequence for these tests.
Without documentation your guess is as good as mine. Certainly
CollectGarbage is of no help with the memory leak problem.

<snip>
function leak_test_globa l(node) {
test_start('glo bal');
node.expando1 = myglobal;
myglobal.push(n ode); // make circular
}

- I think you will find that it does leak.


I have added a new test, leak_test_globa lexpando which is your
version above, and yes, it does leak.

What I don't understand though is what is different about
globals from locals that mean that a global is not trapped
in the closure below:


Function local variables and parameters are stored in the execution
context of a function call as properties of an internal object referred
to in the ECMA spec as the "variable" object. Because inner functions
have access to those parameters and variables after the completion of
the execution of their outer function the "variable" object (at the very
least) must continue to exist when a closure is formed. Thus and
references to DOM Elements held on the "variables" object must also
continue to exist.

Occurrences of an identifier for a global variable within a function do
not effect the "variable" object and will eventually be scope-resolved
against the global object. So no references to the global variables are
preserved within a closure unless they are also assigned to a local
variable or parameter.

A closure might best be perceived as a structure of JavaScript objects,
at minimum: a function object (the inner function) and a "variable"
object, with the function object having a property (internal) that
refers (possibly indirectly) to the "variable" object.

<snip> i also don't understand by node.expando1 = myglobal traps
myglobal, but using node.onclick = function() {...expression
using myglobal...} does not.

<snip>

Your original function did produce a memory leak because the - node -
parameter referred to the DOM Element and assigning the inner function
to the event handler formed a closure. However, no references to that
global object (with the big string) were trapped in the closure (as
explained above) so the leek was too small be exposed by this test
method.

Having the DOM Element directly hold a reference to the global object
while the global object held a reference to the Element produced a
circular reference that did encompass the big string. No closure was
formed in that case but it does demonstrate that global object have no
special role in the context of this problem; all JavaScript objects
(including the internal "variable" object) can form one point in an
unbreakable circular reference on IE.

I will not have an opportunity to look at your new page in detail today
(maybe tomorrow), I will let you know if anything else occurs to me.

Richard.
Jul 20 '05 #4
> Would you mind removing my e-mail address from that page. As I never
respond to unsolicited e-mail from total strangers it can server no
purpose but encourage spam.
Done; now spammers will have to be satisfied with using one of your
1300+ posts
to usenet :).

Occurrences of an identifier for a global variable within a function do
not effect the "variable" object and will eventually be scope-resolved
against the global object. So no references to the global variables are
preserved within a closure unless they are also assigned to a local
variable or parameter.


Thanks; that helps.
I just found this in 262-3 section 10.1.3 which is consistent
with what you say:

Every execution context has associated with it a variable object.
Variables and functions declared in the source text are added as
properties of the variable object. For function code, parameters
are added as properties of the variable object.

Reading some of the surrounding text, you are definitely correct that
global code
(and global variables) are a distinct case from function code, at any
level of nesting.

-mda
Jul 20 '05 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
4488
by: Tony Van | last post by:
I think I know what it is-- objects not being set to nothing when the program is finished with them How can I tell if I have it? How can I code to avoid it? Thanks
21
3898
by: Rabbit63 | last post by:
Hi: I want to show a set of records in the database table on the clicnt browser. I have two ways to do this (writen in JScript): 1.The first way is: <% var sql = "select firstname from table1"; var obj=new ActiveXObject("ADODB.Recordset");
1
1889
by: mark.engelberg | last post by:
I am having trouble identifying the source of a memory leak in a Windows Python program. The basic gist is as follows: 1. Generate a directed graph (approx. 1000 nodes). 2. Write the graph to a file. 3. Use the os.system command to invoke another program which processes the graph file (graphViz), and generates a gif image of the graph. 4....
7
5179
by: George Gre | last post by:
Hi, I wrote a c# programme that listens to incoming TCP requests and services them. This programme is meant to be running as long as the server its installed on is running. So we assume for ever(!). My problem is that I have it running for 2 days now on my pc (win2Ksp3 P4 2GHz,512MB Ram - framework v1.0.3705) and the taskmanager reports...
1
1352
by: anandav2001 | last post by:
Hello developers, I have created an executable(system tray application) in VS.net 2003 using VB.net. My app was taking 30 MB memory(since some web services call are there which happens for each 10 sec checking internet is available or not). Inorder to reduce huge memory consumption, what i used is Public Class MemoryManagement Private...
3
1952
by: Mitch Freed | last post by:
I have been using the JScript eval() method from C# to evaluate conditional logic at run-time. I found that implementing a solution similar to the example posted at: http://www.odetocode.com/Code/80.aspx, seems to handle memory the most efficiently. However, if executing in a tight loop (say, while(true){// jscript eval}, JScript will leak...
2
2000
by: danny.dion | last post by:
Hi ! I have a question about JScript : I have an object class wich dynamically creates a control in the page. Then it binds an event to that control, pointing on one of its methods (the object's). This method, in turn, calls other of its own methods... The binding seems ok and the change() method does get called. But I get an error...
3
5303
by: Jim Land | last post by:
Jack Slocum claims here http://www.jackslocum.com/yui/2006/10/02/3-easy-steps-to-avoid-javascript- memory-leaks/ that "almost every site you visit that uses JavaScript is leaking memory". Anybody know anything about this? Does *Javascript* leak memeory, or does the *browser* leak memory?
22
2252
by: Frank Rizzo | last post by:
I have an object tree that is pretty gigantic and it holds about 100mb of data. When I set the top object to null, I expect that the .NET framework will clean up the memory at some point. However, I am looking at the Task Manager and I don't see the MemUsage column decreasing even after an hour or two. I know that TaskManager may not be the...
0
7641
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language...
0
7957
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. ...
1
7705
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For...
0
8001
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the...
0
6338
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then...
0
3685
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in...
0
3673
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2145
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
0
976
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.