DOM elements not getting destroyed? Memory keeps rising....

DOM elements not getting destroyed? Memory keeps rising....

benjiwbenjiw Posts: 10Questions: 1Answers: 0
edited April 2013 in General
First off; thanks for the amazing plugin. Your work is much appreciated...

I've been tearing my hair out trying to figure out why the memory usage of my page keep climbing into perpetuity every time I use fnreloadjax to refresh the contents of my datatable. Memory keeps climbing until eventually the page shows the "he's dead jim!" message in Chrome (usually after about a full day and swelling to 1 GB+ of memory usage). I'd assume this is because DOM elements aren't getting destroyed properly... or something? Anything you can do to even point me in the right direction would be sincerely appreciated....

Here's the code for the table initialization:

[code]

var oTable = $('#internalnotes').dataTable( {
"bJQueryUI": true,
"bPaginate": false,
"bDestroy": true,
"bDeferRender": true,
"aaSorting": [[ 2, "desc" ]],


"aoColumns": [
{ "sType": "numeric", "bSearchable": false,
"bVisible": false },
{ "iDataSort": 0, sClass: "alignCenter", "sWidth": "10%" },
{ "sType": "date", "sWidth": "15%", "bVisible": false },
{ type: "select", values: [ 'Dept1', 'Dept2', 'Dept3'], sClass: "alignCenter", "sWidth": "10%" },
{"sClass": "alignLeft", "sWidth": "70%" },

],

"sAjaxSource": "GetNewNotes.php?CustomTickers=<?php echo $CustomTickers . "&username=" . $username . "&usertype=" . $usertype?>"


} )

.columnFilter({

aoColumns: [
null,
null,
null,
{ type: "select", values: [ 'Dept1', 'Dept2', 'Dept3', 'Dept4'] },
null

]

});

[/code]

and here is the code that goes within a repeating setTimeout function (loads every 20 seconds) to get the new content (it has some extra code for deciding whether or not to show a notification -- i.e. if a new item has been added)

[code]

var NoteItemCountPre = 0;
var NoteItemCountPost = 0;


$.fn.dataTableExt.oApi.fnReloadAjax = function ( oSettings, sNewSource, fnCallback, bStandingRedraw )
{

NoteItemCountPost = oTable.fnGetData().length;

if ( typeof sNewSource != 'undefined' && sNewSource != null ) {
oSettings.sAjaxSource = sNewSource;
}

// Server-side processing should just call fnDraw
if ( oSettings.oFeatures.bServerSide ) {
this.fnDraw();
return;
}

this.oApi._fnProcessingDisplay( oSettings, true );
var that = this;
var iStart = oSettings._iDisplayStart;
var aData = [];

this.oApi._fnServerParams( oSettings, aData );

oSettings.fnServerData.call( oSettings.oInstance, oSettings.sAjaxSource, aData, function(json) {

/* Clear the old information from the table */
that.oApi._fnClearTable( oSettings );

/* Got the data - add it to the table */
var aData = (oSettings.sAjaxDataProp !== "") ?
that.oApi._fnGetObjectDataFn( oSettings.sAjaxDataProp )( json ) : json;

var NoteItemCountPre = 0;

for ( var i=0 ; i NoteItemCountPost)

{


ShowNotification();

$.titleAlert('New Blog Post', {interval:1000, originalTitleInterval:200});

}

oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();

if ( typeof bStandingRedraw != 'undefined' && bStandingRedraw === true )
{
oSettings._iDisplayStart = iStart;
that.fnDraw( false );
}
else
{
that.fnDraw();
}

that.oApi._fnProcessingDisplay( oSettings, false );

/* Callback user function - for event handlers etc */
if ( typeof fnCallback == 'function' && fnCallback != null )
{
fnCallback( oSettings );
}
}, oSettings );

};

var NoteItemCountPost = NoteItemCountPre;

[/code]


this is what the setTimeout function looks like:


[code]

var reloadNotes = function(){



clearTimeout(timeoutId);



oTable.fnReloadAjax( 'GetNewNotes.php?CustomTickers=<?php echo $CustomTickers ?>&username=<?php echo $username ?>&usertype=<?php echo $usertype ?>');


startCountdown(); // Otherwise it will just run once



};

[/code]


and the countdown that starts the timer

[code]

var timeoutId = 0;

function startCountdown() {



clearTimeout(timeoutId)

timeoutId = setTimeout(reloadNotes, 20000);



};


[/code]

Replies

  • benjiwbenjiw Posts: 10Questions: 1Answers: 0
    I think the problem might be that I have ".on" events attached to elements in the datatable; e.g.

    [code]

    $(document).on("click", "span.read-more", function () {

    clearTimeout(timeoutId);

    setTimeout( startCountdown, 90000);

    });

    [/code]

    Is there any way to free the memory despite having these events attached?
  • allanallan Posts: 63,552Questions: 1Answers: 10,477 Site admin
    Does the problem go away if you remove the event handler? What about if you disable the column filter plug-in?

    Allan
  • benjiwbenjiw Posts: 10Questions: 1Answers: 0
    Thanks very much for responding.

    Interesting.... actually it appears that the problem does NOT go away. The DOM Node Count keeps increasing, alongside memory usage.... I tried removing all the .on event handlers and disabling the column filter plug-in, and it actually looks like memory usage (per Google Chrome's task manager) is increasing *faster*.

    However, it does look like there is some type of garbage collection or DOM node destruction occurring about every 4-5 minutes now, because the DOM node count suddenly drops by ~10,000, only to continue its inexorable march upward. In other words, DOM nodes are getting destroyed, but only back to an elevated level.

    Here's a screenshot of the increasing DOM count from Chrome's developer tools: http://imgur.com/nqfDbDh
  • allanallan Posts: 63,552Questions: 1Answers: 10,477 Site admin
    That's the garbage collection at work. It has a falloff algorithm so as to try and ease the processor burden a bit. If you were to destroy the table and not reload it, that might yikes some interesting information in the Chrome dev tools trace abilities.

    Btw - why are you using both fnReloadAjax and bDestroy? Can you not just use fnReloadAjax?

    Allan
  • benjiwbenjiw Posts: 10Questions: 1Answers: 0
    No reason for using both -- just thought (mistakenly) that enabling bDestroy might help...

    Is there any way to just force destruction of the added DOM nodes? At a loss regarding why they just continue to hang around...
  • benjiwbenjiw Posts: 10Questions: 1Answers: 0
    Still having this issue; does fnreloadajax create a spiraling increase in DOM nodes for everyone or is there something uniquely wrong about my code?

    Thanks
  • allanallan Posts: 63,552Questions: 1Answers: 10,477 Site admin
    > Is there any way to just force destruction of the added DOM nodes?

    They should be destroyed by the call to fnClearTable in fnReloadAjax - unless something else is holding a preference to them. An event handler for example.

    Allan
This discussion has been closed.