Hello together. I''ve recently come across the issue of memory leaks in Javascript, resp. observed that my Prototype/Script.aculo.us application is growing in memory size the longer it runs. I''ve tried to gather information on how to fix this, and while having found several informative sites that explain the issue, I am unsure on how to write my code to allow proper memory allocation. As a test case, I have written a small demo page which calls an Ajax.Request, the responseText is JSON encoded and then populates a list. To test this, it is called several times per click (which takes a while, but that is not the problem). On each click the memory usage increases, although it''s always the same data. I''ve read about creating objects instead of functions (or rather the functions within objects) and then nulling out the objects after the work is done. Please forgive me if that question seems for beginners, but so far I have never bothered with object oriented programming in JS (or rather alltogether) and therefore have problems to accordingly set up the code to allow the memory to be freed. Do I have to use objects to preserver memory, or is there also a way with my current function- approach? I''d really appreciate your help. The application I am aiming for wouldn''t be closed for very long time, if ever (no web page, rather an isolated tool to manage inventories). The HTML code: <a href="#" onclick="searchItemFor(); return false;">Click</a> <ul id="searchResults"></ul> The Javascript functions are: function searchItemFor() { for (var i=0; i<50; i++) searchItem; } function searchItem() { var toURL = ''search.htm''; var results = new Ajax.Request( toURL, { method: ''get'', onComplete: getResponse }); } function getResponse(oReq, oJSN) { var data = eval(oReq.responseText); $(''searchResults'').innerHTML = ''''; //populate the list for (var i = 0; i < data.length; i++) { var newLi = document.createElement("li"); var newText = document.createTextNode(data[i]["item_nr"]); newLi.appendChild(newText); newLi.onclick = new Function ("gotoItem("+ data[i]["item_id"] +");"); $(''searchResults'').appendChild(newLi); } } function gotoItem(id) { alert(id); } --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
On Dec 14, 8:34 pm, Robert <spoon...-hi6Y0CQ0nG0@public.gmane.org> wrote:> Hello together. > > I''ve recently come across the issue of memory leaks in Javascript, > resp. observed that my Prototype/Script.aculo.us application is > growing in memory size the longer it runs. > > I''ve tried to gather information on how to fix this, and while having > found several informative sites that explain the issue, I am unsure on > how to write my code to allow proper memory allocation. > > As a test case, I have written a small demo page which calls an > Ajax.Request, the responseText is JSON encoded and then populates a > list. > To test this, it is called several times per click (which takes a > while, but that is not the problem). > On each click the memory usage increases, although it''s always the > same data. > > I''ve read about creating objects instead of functions (or rather the > functions within objects) and then nulling out the objects after the > work is done. > Please forgive me if that question seems for beginners, but so far I > have never bothered with object oriented programming in JS (or rather > alltogether) and therefore have problems to accordingly set up the > code to allow the memory to be freed. Do I have to use objects to > preserver memory, or is there also a way with my current function- > approach? > > I''d really appreciate your help. The application I am aiming for > wouldn''t be closed for very long time, if ever (no web page, rather an > isolated tool to manage inventories). > > The HTML code: > <a href="#" onclick="searchItemFor(); return false;">Click</a> > <ul id="searchResults"></ul> > > The Javascript functions are: > function searchItemFor() > { > for (var i=0; i<50; i++) > searchItem;I guess that is: searchItem(); :-) [...]> > function getResponse(oReq, oJSN) > { > var data = eval(oReq.responseText); > $(''searchResults'').innerHTML = '''';I would try using DOM methods to remove the content rather than innerHTML, which is known not to properly remove form elements from memory at least. Try something like: var el = $(''searchResults''); el.parentNode.replaceChild(el.cloneNode(false), el); or while (el.firstChild) el.removeChild(el.firstChild); -- Rob --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
On 14 Dez., 12:28, RobG <rg...-AFFH1GffN5hPR4JQBCEnsQ@public.gmane.org> wrote:> > function searchItemFor() > > { > > for (var i=0; i<50; i++) > > searchItem; > > I guess that is: > > searchItem(); > > :-)Yes indeed. I was wondering why I couldn''t use brackets within the Ajax.Request call ("onComplete: getResponse"), so I tried to write a call without brackets within a ''normal'' function as well, which obviously doesn''t work (and which I forgot to change here).> I would try using DOM methods to remove the content rather than > innerHTML, which is known not to properly remove form elements from > memory at least. Try something like: > > var el = $(''searchResults''); > el.parentNode.replaceChild(el.cloneNode(false), el); > > or > > while (el.firstChild) el.removeChild(el.firstChild);Ok, so I tried that, but that didn''t help much in memory usage. Private Bytes and Working Size (whatever they mean exactly, still haven''t that figured out 100% - using ProcessExplorer by sysinternals) were around 2 MB less than with innerHTML, but Virtual Size had increased by 5 MB. Both were tested with a freshly opened IE6 with only that test page opened (didn''t test it with FF yet). Also, I don''t think this is the main problem, as it was only an example for an AJAX Request and could have been an Ajax.Updater as well.> -- > RobGreetings, Robert :-) --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
The short version: in IE, when you remove an element from the DOM, you should also remove its event handlers to prevent circular references. When you assign events using attributes (onclick, onload, etc.), Doug Crockford''s "purge" function is an easy way to do this [1]. When you assign events within Prototype, it''s even easier -- just call Event.stopObserving(someNode) or someNode.stopObserving() to remove all that node''s handlers. Also, use "el.update()" instead of setting the innerHTML to an empty string. That way your code will be future proof when we decide to handle this automatically inside Element#update (hopefully in 1.6.1). Cheers, Andrew [1] http://www.crockford.com/javascript/memory/leak.html On Dec 14, 8:24 am, Robert <spoon...-hi6Y0CQ0nG0@public.gmane.org> wrote:> On 14 Dez., 12:28, RobG <rg...-AFFH1GffN5hPR4JQBCEnsQ@public.gmane.org> wrote: > > > > function searchItemFor() > > > { > > > for (var i=0; i<50; i++) > > > searchItem; > > > I guess that is: > > > searchItem(); > > > :-) > > Yes indeed. I was wondering why I couldn''t use brackets within the > Ajax.Request call ("onComplete: getResponse"), so I tried to write a > call without brackets within a ''normal'' function as well, which > obviously doesn''t work (and which I forgot to change here). > > > I would try using DOM methods to remove the content rather than > > innerHTML, which is known not to properly remove form elements from > > memory at least. Try something like: > > > var el = $(''searchResults''); > > el.parentNode.replaceChild(el.cloneNode(false), el); > > > or > > > while (el.firstChild) el.removeChild(el.firstChild); > > Ok, so I tried that, but that didn''t help much in memory usage. > Private Bytes and Working Size (whatever they mean exactly, still > haven''t that figured out 100% - using ProcessExplorer by sysinternals) > were around 2 MB less than with innerHTML, but Virtual Size had > increased by 5 MB. > Both were tested with a freshly opened IE6 with only that test page > opened (didn''t test it with FF yet). > > Also, I don''t think this is the main problem, as it was only an > example for an AJAX Request and could have been an Ajax.Updater as > well. > > > -- > > Rob > > Greetings, > Robert :-)--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
On Dec 15, 7:56 am, Andrew Dupont <goo...-TiabPMV39B5K4mp1Ns0Z8Q@public.gmane.org> wrote:> The short version: in IE, when you remove an element from the DOM, you > should also remove its event handlers to prevent circular references.That is good advice where handlers have been added dynamically, but is only really necessary if you have created circular references to DOM elements in the first place. The OPs code doesn''t do that - it uses Function as a constructor to avoid closures, therefore no circular references are formed.> When you assign events using attributes (onclick, onload, etc.), Doug > Crockford''s "purge" function is an easy way to do this [1].And if you replace the anonymous function in Douglas'' code with a Function statement, or re-factor it to avoid the circular reference, there is no memory leak.> assign events within Prototype, it''s even easier -- just call > Event.stopObserving(someNode) or someNode.stopObserving() to remove > all that node''s handlers. > > Also, use "el.update()" instead of setting the innerHTML to an empty > string.If you pass an empty string to update(), that is exactly what it will do.> That way your code will be future proof when we decide to > handle this automatically inside Element#update (hopefully in 1.6.1).That does not help the OP understand the memory leak he is experiencing - the leak is occurring despite there not being any circular references or closures. -- Rob --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
On Dec 15, 12:24 am, Robert <spoon...-hi6Y0CQ0nG0@public.gmane.org> wrote:> On 14 Dez., 12:28, RobG <rg...-AFFH1GffN5hPR4JQBCEnsQ@public.gmane.org> wrote: > > > > function searchItemFor() > > > { > > > for (var i=0; i<50; i++) > > > searchItem; > > > I guess that is: > > > searchItem(); > > > :-) > > Yes indeed. I was wondering why I couldn''t use brackets within the > Ajax.Request call ("onComplete: getResponse"),Request expects to be passed a function reference. If you put the call operator after the function name, you pass the results of executing the function, which may or may not return a function reference (but probably doesn''t). [...]> > I would try using DOM methods to remove the content rather than > > innerHTML, which is known not to properly remove form elements from > > memory at least. Try something like: > > > var el = $(''searchResults''); > > el.parentNode.replaceChild(el.cloneNode(false), el); > > > or > > > while (el.firstChild) el.removeChild(el.firstChild); > > Ok, so I tried that, but that didn''t help much in memory usage. > Private Bytes and Working Size (whatever they mean exactly, still > haven''t that figured out 100% - using ProcessExplorer by sysinternals) > were around 2 MB less than with innerHTML, but Virtual Size had > increased by 5 MB. > Both were tested with a freshly opened IE6 with only that test page > opened (didn''t test it with FF yet). > > Also, I don''t think this is the main problem, as it was only an > example for an AJAX Request and could have been an Ajax.Updater as > well.I refactored your code to remove the AJAX request and do not see any leaks in IE, therefore I expect your issue has nothing to do with the handler you assign to the li elements, or the way you remove them from the document. Try the code below - do you still get a memory leak? I''ve dummied the response text to include only the object properties I could infer from your code - is there other stuff in there? Maybe that is the source of your leak. function searchItemFor() { var i = 50; while (i--) searchItem(); } function searchItem() { var t = new Date(); var oReq = {}; var txt = []; for (var i=0; i<50; i++) { txt.push( ''{item_nr:"'' + i + '': '' + t + ''", item_id:"foo_'' + i + ''"}'' ); } oReq.responseText = ''['' + txt.join('','') + '']''; getResponse(oReq, ''''); } function getResponse(oReq, oJSN) { var data = eval(oReq.responseText); $(''searchResults'').innerHTML = ''''; //populate the list for (var i = 0; i < data.length; i++) { var newLi = document.createElement("li"); var newText = document.createTextNode(data[i]["item_nr"]); newLi.appendChild(newText); newLi.onclick = new Function ( ''gotoItem("'' + data[i][''item_id''] + ''");'' ); $(''searchResults'').appendChild(newLi); } } function gotoItem(id) { alert(id); } -- Rob --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
On 15 Dez., 04:26, RobG <rg...-AFFH1GffN5hPR4JQBCEnsQ@public.gmane.org> wrote:> On Dec 15, 7:56 am, Andrew Dupont <goo...-TiabPMV39B5K4mp1Ns0Z8Q@public.gmane.org> wrote: > > > The short version: in IE, when you remove an element from the DOM, you > > should also remove its event handlers to prevent circular references. > > That is good advice where handlers have been added dynamically, but is > only really necessary if you have created circular references to DOM > elements in the first place. The OPs code doesn''t do that - it uses > Function as a constructor to avoid closures, therefore no circular > references are formed.This seems like a decent reason to explain the way I code, but to be honest, the truth is that at the moment this is the only way I actually know how to write javascript code. :) Also, the code excerpt in my OP is only that, an excerpt and an example. Take that code and think about an application with dozens of Ajax.Requests, Ajax.Updaters, Ajax.Autocmpleter, etc, where not only JSON code is transferred, but also plain HTML code generated by PHP. On 14 Dez., 22:56, Andrew Dupont <goo...-TiabPMV39B5K4mp1Ns0Z8Q@public.gmane.org> wrote:> When you assign events using attributes (onclick, onload, etc.), Doug > Crockford''s "purge" function is an easy way to do this [1]. When you > assign events within Prototype, it''s even easier -- just call > Event.stopObserving(someNode) or someNode.stopObserving() to remove > all that node''s handlers.So thinking further about this, I''d need to call this purge function everytime I use an Ajax.Updater where I''m transferring plain HTML where the onclick, etc events are already in the code (I know this isn''t the most sophisticated way, but it''s so damn easy)? I haven''t assigned events through Prototype yet, despite having a few element.onclick = function {} calls within my code, which basically would be the only ones I could change "easily" to event.observe (at least I guess). On 15 Dez., 04:34, RobG <rg...-AFFH1GffN5hPR4JQBCEnsQ@public.gmane.org> wrote:> I refactored your code to remove the AJAX request and do not see any > leaks in IE, therefore I expect your issue has nothing to do with the > handler you assign to the li elements, or the way you remove them from > the document. > > Try the code below - do you still get a memory leak? I''ve dummied the > response text to include only the object properties I could infer from > your code - is there other stuff in there? Maybe that is the source > of your leak. > > [... code ...]In the original test page, there is a JSON string being transferred, with some more data than only the item number. But I tried your code and I am still seeing an increase in memory usage on each iteration of searchItemFor(). I''ve uploaded a spreadsheet on http://spreadsheets.google.com/pub?key=pAmGBzNA8o7c30HgfC_ibcg Working Size, Private Bytes and Virtual Size are noted down as presented by ProcessExplorer form sysinternals (www.sysinternals.com, meanwhile acquired by Microsoft) right after the function has completed. It seems to flatten out at around 16MB increased memory after 10 iterations (10 times I clicked on the link to call searchItemFor()). So if you didn''t experience a memory leak, is this expected behaviour? This test was done on Firefox now, right after a PC reboot and with nothing else opened than my test page (and back at home now, yesterday was at the office). I did read that Firefox keeps the memory as used by the largest object it has encountered for later use, but as here there is always the same size of data, shouldn''t the memory usage be roughly the same for each iteration? Or is it maybe because of the use of the href="#" together with onclick="", that FF somehow caches the old pages in histroy despite you''ve never left the page? I really appreciate your help. I have never crossed the line to object oriented programming so far, so I''m a bit confused on what the best approach is, or if it would help me at all. I was planning to dig deeper into the issue today, if I find the time. Greetings, Robert --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
On Dec 15, 8:55 pm, Robert <spoon...-hi6Y0CQ0nG0@public.gmane.org> wrote:> On 15 Dez., 04:26, RobG <rg...-AFFH1GffN5hPR4JQBCEnsQ@public.gmane.org> wrote: > > > On Dec 15, 7:56 am, Andrew Dupont <goo...-TiabPMV39B5K4mp1Ns0Z8Q@public.gmane.org> wrote: > > > > The short version: in IE, when you remove an element from the DOM, you > > > should also remove its event handlers to prevent circular references. > > > That is good advice where handlers have been added dynamically, but is > > only really necessary if you have created circular references to DOM > > elements in the first place. The OPs code doesn''t do that - it uses > > Function as a constructor to avoid closures, therefore no circular > > references are formed. > > This seems like a decent reason to explain the way I code, but to be > honest, the truth is that at the moment this is the only way I > actually know how to write javascript code. :)There are a variety of ways to attach handlers to dynamically created elements, they each have their pros and cons.> Also, the code excerpt in my OP is only that, an excerpt and an > example. > Take that code and think about an application with dozens of > Ajax.Requests, Ajax.Updaters, Ajax.Autocmpleter, etc, where not only > JSON code is transferred, but also plain HTML code generated by PHP.There are no memory leak issues associated with that. The issue of memory leaks and javascript is related to IE and IE only, it is not an issue with other browsers, or a general issue with using XMLHttpRequest over any other method of page updates.> On 14 Dez., 22:56, Andrew Dupont <goo...-TiabPMV39B5K4mp1Ns0Z8Q@public.gmane.org> wrote: > > > When you assign events using attributes (onclick, onload, etc.), Doug > > Crockford''s "purge" function is an easy way to do this [1]. When you > > assign events within Prototype, it''s even easier -- just call > > Event.stopObserving(someNode) or someNode.stopObserving() to remove > > all that node''s handlers. > > So thinking further about this, I''d need to call this purge function > everytime I use an Ajax.Updater where I''m transferring plain HTML > where the onclick, etc events are already in the code (I know this > isn''t the most sophisticated way, but it''s so damn easy)?No, you don''t have to do that. There is one specific memory leak related to IE that we are talking about (although IE has others), and that is closures and circular references involving DOM objects. Closures themselves do not cause a problem in IE. If you are adding elements to the page using innerHTML that have in- ilne handlers, you don''t have to worry about the IE memory leak discussed here. It is simply not necessary to run a purge for handlers on every element you remove from the DOM.> I haven''t assigned events through Prototype yet, despite having a few > element.onclick = function {} calls within my code, which basically > would be the only ones I could change "easily" to event.observe (at > least I guess).Whenever you use a function expression to assign a handler, e.g. function foo(){ var el = document.createElement(''div''); el.onclick = function(){...}; } Then the anonymous function has a closure back to the outer function, foo. Therefore, the activation object created when foo was called remains unavailable for garbage collection until either the DOM element that has the handler is made available for garbage collection or the page is unloaded. IE''s problem is that the circular reference is not broken when it should be and the garbage collector will not remove foo from memory until the browser application is closed (i.e. all IE windows are closed). One simple solution is to not leave the circular reference and set el to null when you are finished with it - no circular reference, no memory leak, no need for ''purge''. Another is to use the built-in Function object as a constructor (as for your OP). Yet another is to always use function references. How many do you want? :-)> On 15 Dez., 04:34, RobG <rg...-AFFH1GffN5hPR4JQBCEnsQ@public.gmane.org> wrote: > > > I refactored your code to remove the AJAX request and do not see any > > leaks in IE, therefore I expect your issue has nothing to do with the > > handler you assign to the li elements, or the way you remove them from > > the document. > > > Try the code below - do you still get a memory leak? I''ve dummied the > > response text to include only the object properties I could infer from > > your code - is there other stuff in there? Maybe that is the source > > of your leak. > > > [... code ...] > > In the original test page, there is a JSON string being transferred, > with some more data than only the item number. > But I tried your code and I am still seeing an increase in memory > usage on each iteration of searchItemFor(). > I''ve uploaded a spreadsheet onhttp://spreadsheets.google.com/pub?key=pAmGBzNA8o7c30HgfC_ibcgAn increase in memory usage is not an issue per se. It is only an issue if the memory should have been released but wasn''t. If you navigate away from the page, is memory released?> Working Size, Private Bytes and Virtual Size are noted down as > presented by ProcessExplorer form sysinternals (www.sysinternals.com, > meanwhile acquired by Microsoft) right after the function has > completed. It seems to flatten out at around 16MB increased memory > after 10 iterations (10 times I clicked on the link to call > searchItemFor()).Which says to me that memory is being handled just fine.> > So if you didn''t experience a memory leak, is this expected behaviour?Exact, no, but I certainly wouldn''t call that a memory leak. You have no control over how a browser allocates or handles memory, just let it do its thing. All you can do is keep usage reasonable and don''t waste it.> This test was done on Firefox now, right after a PC reboot and with > nothing else opened than my test page (and back at home now, yesterday > was at the office). > I did read that Firefox keeps the memory as used by the largest object > it has encountered for later use, but as here there is always the same > size of data, shouldn''t the memory usage be roughly the same for each > iteration?There are no known memory leaks for Firefox related to using script in web pages. What you are seeing is Firefox handling memory presumably as it has been coded to do.> Or is it maybe because of the use of the href="#" together with > onclick="", that FF somehow caches the old pages in histroy despite > you''ve never left the page?I have no idea, I wouldn''t use an A element where a button seems more appropriate. Returning false from the handler should prevent navigation (if the script runs correctly).> > I really appreciate your help. I have never crossed the line to object > oriented programming so far, so I''m a bit confused on what the best > approach is, or if it would help me at all. I was planning to dig > deeper into the issue today, if I find the time.Javascript is not strictly an object oriented language, it is object based. You can implement a number of OO principles, however the underlying prototype inheritance scheme is quite different to traditional OO inheritance. -- Rob --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
Ok, thank you for your help, things are starting to become much clearer now. At first, the memory increase I was experiencing with FF was due to the Firebug addon. After disabling it, my memory consumption went from the reported 16 MB down to 1.5 MB. Also I don''t see an increase on repeated iterations, unlike with Firebug, where it was like 4 MB, 8 MB, 10 MB, etc. Maybe Firebug is leaking itself, or has an history function in some way. On 16 Dez., 04:19, RobG <rg...-AFFH1GffN5hPR4JQBCEnsQ@public.gmane.org> wrote:> On Dec 15, 8:55 pm, Robert <spoon...-hi6Y0CQ0nG0@public.gmane.org> wrote: > > > Also, the code excerpt in my OP is only that, an excerpt and an > > example. > > Take that code and think about an application with dozens of > > Ajax.Requests, Ajax.Updaters, Ajax.Autocmpleter, etc, where not only > > JSON code is transferred, but also plain HTML code generated by PHP. > > There are no memory leak issues associated with that. The issue of > memory leaks and javascript is related to IE and IE only, it is not an > issue with other browsers, or a general issue with using > XMLHttpRequest over any other method of page updates.So I only have to worry about IE for memory leaks (not memory usage itself)? There are no known leaks for FireFox or Opera that require to purge or nullify an element/object/whatever to prevent them? Does IE7 suffer from the same leaks as IE6, or did they fix some, introduced others, changed the way to circumvent them, etc?> > On 14 Dez., 22:56, Andrew Dupont <goo...-TiabPMV39B5K4mp1Ns0Z8Q@public.gmane.org> wrote: > > > > When you assign events using attributes (onclick, onload, etc.), Doug > > > Crockford''s "purge" function is an easy way to do this [1]. When you > > > assign events within Prototype, it''s even easier -- just call > > > Event.stopObserving(someNode) or someNode.stopObserving() to remove > > > all that node''s handlers. > > > So thinking further about this, I''d need to call this purge function > > everytime I use an Ajax.Updater where I''m transferring plain HTML > > where the onclick, etc events are already in the code (I know this > > isn''t the most sophisticated way, but it''s so damn easy)? > > No, you don''t have to do that. There is one specific memory leak > related to IE that we are talking about (although IE has others), and > that is closures and circular references involving DOM objects. > Closures themselves do not cause a problem in IE. > > If you are adding elements to the page using innerHTML that have in- > ilne handlers, you don''t have to worry about the IE memory leak > discussed here. It is simply not necessary to run a purge for > handlers on every element you remove from the DOM.Hm, that is not exactly what I was experiencing yesterday while running my tests. While not a big issue, I noticed a difference of about 3-4 MB when I tested Ajax.Updater with and without the Purge function, having inline onclick events. Also the memory didn''t really leak, IE only used more memory after the 2nd iteration and didn''t really add up afterwards. It is not much, and maybe only a coincidence. I''ll try to verify this test.> > Working Size, Private Bytes and Virtual Size are noted down as > > presented by ProcessExplorer form sysinternals (www.sysinternals.com, > > meanwhile acquired by Microsoft) right after the function has > > completed. It seems to flatten out at around 16MB increased memory > > after 10 iterations (10 times I clicked on the link to call > > searchItemFor()). > > Which says to me that memory is being handled just fine.With Firebug of, it is indeed. As explained above, Firebug adds around 4 MB of memory on each iteration, flatting out after some time. Thanks again for the help. It seems for the time being I can sneak out of learning object oriented for Javascript then. ;-) Greetings, Robert --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
On Dec 14, 9:26 pm, RobG <rg...-AFFH1GffN5hPR4JQBCEnsQ@public.gmane.org> wrote:> On Dec 15, 7:56 am, Andrew Dupont <goo...-TiabPMV39B5K4mp1Ns0Z8Q@public.gmane.org> wrote: > > > The short version: in IE, when you remove an element from the DOM, you > > should also remove its event handlers to prevent circular references. > > That is good advice where handlers have been added dynamically, but is > only really necessary if you have created circular references to DOM > elements in the first place. The OPs code doesn''t do that - it uses > Function as a constructor to avoid closures, therefore no circular > references are formed. > [snip] > And if you replace the anonymous function in Douglas'' code with a > Function statement, or re-factor it to avoid the circular reference, > there is no memory leak.Not so. The long version is that I''ve been able to produce a leak in IE even when adding observers that do not create implicit circular references through closures. More specifically, I''ve got a test case where I create 10,000 SPANs, Event.observe each with a handler of Prototype.K (no closure created), then remove each element. Doing so creates a leak: memory usage increases by a predictable amount each time I refresh the page. Calling Event.stopObserving on the element before it''s removed prevents the leak: memory usage goes up on page load, but goes back down on unload. I''ve learned that it''s almost useless to logically "prove" that code has no memory leaks in IE. The code scenarios that would cause IE6 to leak memory are myriad; the most notorious is the one you describe, but there are plenty of others. Reduced test cases in Drip [1] are the most reliable way to diagnose memory leaks. Cheers, Andrew [1] http://www.outofhanwell.com/ieleak/index.php?title=Main_Page> > > When you assign events using attributes (onclick, onload, etc.), Doug > > Crockford''s "purge" function is an easy way to do this [1]. > > > > assign events within Prototype, it''s even easier -- just call > > Event.stopObserving(someNode) or someNode.stopObserving() to remove > > all that node''s handlers. > > > Also, use "el.update()" instead of setting the innerHTML to an empty > > string. > > If you pass an empty string to update(), that is exactly what it will > do. > > > That way your code will be future proof when we decide to > > handle this automatically inside Element#update (hopefully in 1.6.1). > > That does not help the OP understand the memory leak he is > experiencing - the leak is occurring despite there not being any > circular references or closures. > > -- > Rob--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---