[ 11 posts ] Go to page 1, 2 Next

Eric Durbin

YUI Contributor

  • Username: edurbin
  • Joined: Wed Jul 13, 2011 5:41 am
  • Posts: 50
  • GitHub: edurbin
  • Gists: edurbin
  • Offline
  • Profile

yui2 datatable memory leak

Post Posted: Thu Dec 01, 2011 3:16 pm
+0-
The following code results in a memory leak with detached dom subtrees holding references to javascript objects. They can be viewed in the chrome heap profiler. If you let this run, you will see that it quickly exhausts your browsers memory.

The basic datatable example from the examples page also exhibits this problem.

Code:
<!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=utf-8">
<title>Basic Example</title>

<style type="text/css">
/*margin and padding on body element
  can introduce errors in determining
  element position and are not recommended;
  we turn them off as a foundation for YUI
  CSS treatments. */
body {
   margin:0;
   padding:0;
}
</style>

<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.9.0/build/fonts/fonts-min.css" />
<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.9.0/build/datatable/assets/skins/sam/datatable.css" />
<script type="text/javascript" src="http://yui.yahooapis.com/2.9.0/build/yahoo-dom-event/yahoo-dom-event.js"></script>

<script type="text/javascript" src="http://yui.yahooapis.com/2.9.0/build/dragdrop/dragdrop-min.js"></script>
<script type="text/javascript" src="http://yui.yahooapis.com/2.9.0/build/element/element-min.js"></script>
<script type="text/javascript" src="http://yui.yahooapis.com/2.9.0/build/datasource/datasource-min.js"></script>
<script type="text/javascript" src="http://yui.yahooapis.com/2.9.0/build/event-delegate/event-delegate-min.js"></script>
<script type="text/javascript" src="http://yui.yahooapis.com/2.9.0/build/datatable/datatable-min.js"></script>

<script type="text/javascript">
var counter = 0;
   var myDataTable;
function populate()
{
   var innerElement = document.createElement('div');
   innerElement.id = 'inner';
   document.getElementById('outer').appendChild(innerElement);

   var data = {
   bookorders: [
      {id:"po-0167", date:new Date(1980, 2, 24), quantity:1, amount:4, title:"A Book About Nothing"},
      {id:"po-0783", date:new Date("January 3, 1983"), quantity:null, amount:12.12345, title:"The Meaning of Life"},
      {id:"po-0297", date:new Date(1978, 11, 12), quantity:12, amount:1.25, title:"This Book Was Meant to Be Read Aloud"},
      {id:"po-1482", date:new Date("March 11, 1985"), quantity:6, amount:3.5, title:"Read Me Twice"}
   ]
   }

   var createTable = function() {
      var myColumnDefs = [
      {key:"id", sortable:true, resizeable:true},
      {key:"date", formatter:YAHOO.widget.DataTable.formatDate, sortable:true, sortOptions:{defaultDir:YAHOO.widget.DataTable.CLASS_DESC},resizeable:true},
      {key:"quantity", formatter:YAHOO.widget.DataTable.formatNumber, sortable:true, resizeable:true},
      {key:"amount", formatter:YAHOO.widget.DataTable.formatCurrency, sortable:true, resizeable:true},
      {key:"title", sortable:true, resizeable:true}
      ];
   
      var myDataSource = new YAHOO.util.DataSource(data.bookorders);
      myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSARRAY;
      myDataSource.responseSchema = {
      fields: ["id","date","quantity","amount","title"]
      };
   
      myDataTable = new YAHOO.widget.DataTable("inner",
         myColumnDefs, myDataSource, {caption:"DataTable Caption" + counter});
         
      return {
      oDS: myDataSource,
      oDT: myDataTable
      };

   }();

   counter++;
   setTimeout("clear_data()", 100);
}


function clear_data()
{
      myDataTable.destroy();
      myDataTable = null;
   document.getElementById('outer').innerHTML = '';
   start_test();
}


function start_test()
{
   populate();
}


</script>

</head>

<body class=" yui-skin-sam">
<div id="top1">
   <input type="button" onclick="populate();" value="Add Data" style="z-index: 5000;">
   <input type="button" onclick="clear_data();" value="Clear Data" style="z-index: 5000;">
   <input type="button" onclick="start_test();" value="Start Test" style="z-index: 5000;">
</div>

   <div id="outer">
   </div>
</body>
</html>


Last edited by edurbin on Fri Dec 02, 2011 6:09 am, edited 1 time in total.

Todd Smith

YUI Contributor

  • Username: stlsmiths
  • Joined: Thu Nov 05, 2009 10:03 am
  • Posts: 675
  • GitHub: stlsmiths
  • Gists: stlsmiths
  • IRC: t_smith
  • Offline
  • Profile

Re: yui2 datatable memory leak

Post Posted: Thu Dec 01, 2011 7:45 pm
+0-
Since YUI 2 is now in maintenance mode I'm not sure that anybody will propose to make any bug fixes, at least not from the YUI team.

Satyam

YUI Contributor

  • Username: Satyam
  • Joined: Tue Dec 09, 2008 12:34 am
  • Posts: 2016
  • Location: Sitges, Spain
  • GitHub: Satyam
  • Gists: Satyam
  • IRC: DevaSatyam
  • YUI Developer
  • Offline
  • Profile

Re: yui2 datatable memory leak

Post Posted: Fri Dec 02, 2011 1:23 am
+0-
you must call method destroy() to free the resources taken by the DataTable. Wiping out the HTML it produces is not enough, you leave many other things behind. JavaScript knows nothing about destructors, it is up to you to call destroy()

Eric Durbin

YUI Contributor

  • Username: edurbin
  • Joined: Wed Jul 13, 2011 5:41 am
  • Posts: 50
  • GitHub: edurbin
  • Gists: edurbin
  • Offline
  • Profile

Re: yui2 datatable memory leak

Post Posted: Fri Dec 02, 2011 6:10 am
+0-
Satyam wrote:
you must call method destroy() to free the resources taken by the DataTable. Wiping out the HTML it produces is not enough, you leave many other things behind. JavaScript knows nothing about destructors, it is up to you to call destroy()


See example above, I'm calling myDataTable.destroy() and then nulling out the object with the exact same behavior. Still growing in number of detached dom subtrees with javascript references and exhausts browser memory.

Satyam

YUI Contributor

  • Username: Satyam
  • Joined: Tue Dec 09, 2008 12:34 am
  • Posts: 2016
  • Location: Sitges, Spain
  • GitHub: Satyam
  • Gists: Satyam
  • IRC: DevaSatyam
  • YUI Developer
  • Offline
  • Profile

Re: yui2 datatable memory leak

Post Posted: Fri Dec 02, 2011 8:43 am
+0-
As Todd says, there is not further work on YUI2. However, if you want to refresh the DataTable, you might do so keeping the same DataTable instance and refreshing the data.

This might help:

http://www.satyam.com.ar/yui/#requery

Eric Durbin

YUI Contributor

  • Username: edurbin
  • Joined: Wed Jul 13, 2011 5:41 am
  • Posts: 50
  • GitHub: edurbin
  • Gists: edurbin
  • Offline
  • Profile

Re: yui2 datatable memory leak

Post Posted: Mon Dec 05, 2011 10:44 am
+0-
The datatable doesn't remove the event listeners properly on destroy(). There are several 'mouseout' and 'mouseover' event handlers lingering after destroy() is called. Commenting out the delegation for 'mouseenter' and 'mouseleave' eliminates the memory leak.

Eric Durbin

YUI Contributor

  • Username: edurbin
  • Joined: Wed Jul 13, 2011 5:41 am
  • Posts: 50
  • GitHub: edurbin
  • Gists: edurbin
  • Offline
  • Profile

Re: yui2 datatable memory leak

Post Posted: Mon Dec 05, 2011 1:37 pm
+0-
There's a problem with the delegates[] array that is leaking in event-delegate. When we add a delegate we push an item on to the delegates[] array. When an item is removed it finds the first index that matches that event in the delegates array and then does an array splice, only removing the first element it finds instead of all elements in the array even though we may have added 6 events to different subcomponents of the container as in the case of the datatable.

Eric Durbin

YUI Contributor

  • Username: edurbin
  • Joined: Wed Jul 13, 2011 5:41 am
  • Posts: 50
  • GitHub: edurbin
  • Gists: edurbin
  • Offline
  • Profile

Re: yui2 datatable memory leak

Post Posted: Tue Dec 13, 2011 7:54 am
+0-
https://gist.github.com/1472618

Sean Fitzsimmons

  • Username: seanf
  • Joined: Wed Sep 16, 2009 6:16 am
  • Posts: 78
  • Location: Baltimore, Maryland, USA
  • Offline
  • Profile

Re: yui2 datatable memory leak

Post Posted: Thu Dec 15, 2011 5:51 am
+0-
Eric,

Thanks for the patch. That memory leak has been a major problem for us since our ScrollingDataTables are large. I had to manually cut in your new event-mouseenter module as well as the changes to destroy (we are on an intranet and the import request will take longer than I'm willing to wait), but your remove function never gets called. Are there any other changes that need to be made? Can you verify that the remove function gets called?

Thanks, Sean

Eric Durbin

YUI Contributor

  • Username: edurbin
  • Joined: Wed Jul 13, 2011 5:41 am
  • Posts: 50
  • GitHub: edurbin
  • Gists: edurbin
  • Offline
  • Profile

Re: yui2 datatable memory leak

Post Posted: Thu Dec 15, 2011 8:58 am
+0-
No, I don't think it does. I think remove() is only called when removing listeners, not when calling removeDelegate(). It should be calling the removeDelegate() function on destroy() and removing the events that were delegated on initialization.
  [ 11 posts ] Go to page 1, 2 Next
Display posts from previous:  Sort by  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum