I have a lot of memory leaks with datatables and need tips on how to improve

I have a lot of memory leaks with datatables and need tips on how to improve

phawellphawell Posts: 28Questions: 12Answers: 1

I am using angularjs
Version of my angular-datatables lib is: v0.6.3-dev
Version of my jquery datatable lib is: DataTables 1.10.9

The memory leaks increase every time I click in new page of the paging. Using ajax I refres the datatable but dont know why a lots of DOM became detached and became memory leak.

The pagination is only 10 ROWS every page and only get those ROWS form server.
That should not leaking so much memory,
What I can be doing wrong?

Find it out using the chrome inspector.

First I create columns like this:
$scope.dtColumnsCases = [
DTColumnBuilder.newColumn('idCaso').withTitle(idCasoTitle).withOption('defaultContent', '').renderWith(function (data, type, full, meta) {
return "<span ng-class=\"{'row-selected': isInteractionAssignedToCase(" + full.idCaso +")}\">" + full.idCaso + "</span>";
}), .....
]

Then create my datatable
$scope.dtOptionsCases = DTOptionsBuilder.newOptions()
.withOption('order', [[4, 'asc']])
.withOption('ajax', {...}
.withDataProp('data')
.withOption('processing', true)
.withOption('serverSide', true)
.withOption('createdRow', function (row, data, dataIndex) {
$compile(angular.element(row).contents())($scope);
})
.withOption('headerCallback', function (header) {
$compile(angular.element(header).contents())($scope);
})
.withPaginationType('simple_numbers')
.withDisplayLength(9)
.withOption('autoWidth', true)
.withOption('lengthChange', false)
.withOption('scrollCollapse', true)
.withOption('scrollY', "100%")
.withOption('ordering', true)
.withOption('info', false);

My html is:

Every time I need reload I do this:

            $scope.dtInstance.reloadData(null,true);

All is working ok but a lot of memory leak.

What must I do to be sure I destroid all DOM and Javascript and listener before reload.
I just need to keep the datatable object in order to do the reload and fill its data in each reload but in every reload I need be sure all OLDS ROWS and all data is deleted.

In every change of page and every reload I find out the function in withOption('createdRow', function (row, data, dataIndex) { .. } is executing for every file. Could it be I must destroy manually previo DTOptionsBuilder or the DOM?

Please help, is very important because our customers complain about so much resource consumption.

It would be of great help some track of where to eliminate in each reload DOM so that the garbage collector does not lose those data.

Ask me for any information you think necessary for what you think is convenient

Thanks in advance

Answers

  • allanallan Posts: 63,464Questions: 1Answers: 10,466 Site admin

    You'll probably need to consult the Angular DataTables author I'm afraid. I'm guessing that either there are events being bound which are not released, or elements which something is holding a reference to. If this can be reproduced with just plain DataTables, then yes, it would be a DataTables issue, but I'm not aware of any such issues in the core at the moment.

    In every change of page and every reload I find out the function in withOption('createdRow', function (row, data, dataIndex) { .. } is executing for every file.

    That is expected. createdRow will execute for every row - that is what it is designed for. If you are binding events in there, then that is the issue. You need to also unbind them.

    Allan

  • phawellphawell Posts: 28Questions: 12Answers: 1

    Thank you for your help. Just one more clarification:
    If I want to insert a code for clean all events in all rows before execution de createdRow for every row

    withOption('createdRow', function (row, data, dataIndex) { .. }

    Where must I put this previous clean code so when start createdRow all the old binded events where removes.

    I am looking for a function that is executed as a pre-preparation before the others

    1 Is there a .withOption() with a function that allways execute before start the createdRow function.

    2 ¿Would it be correct that in this pre-initialization function before starting the createdRow, besides eliminating the binded events I delete the rows manually?

    for example dataTable.rows().clear

    And this function can clear old DOM besides elimitating de binded events.

    Thank you

  • phawellphawell Posts: 28Questions: 12Answers: 1
    edited October 2017

    I do not know if I explained well. What I want to know is in which part of the DTOptionsBuilder.newOptions definition I must put the code to clean the old events before datatables go on to create the new rows.

    I do not know if it will be a preprocess function type:

    .withOption ('preprocessing', function {}) or so

    I ask this because when you click on each button in the pagination, the component automates and executes the function of updating rows:

    .withOption('createdRow', function (row, data, dataIndex) { $compile(angular.element(row).contents())($scope); })

    I do not know if it is correct to assume that there must be a preprocess function that can be registered in the component and that it be launched automatically before each row update in an automated way and in which to be able to delete DOM and Events and free and clean all old stuff before renew rows and avoid memory leaks.

    Thank you for your help, sorry if my english is not very well.

  • allanallan Posts: 63,464Questions: 1Answers: 10,466 Site admin

    I am looking for a function that is executed as a pre-preparation before the others

    The preDrawCallback config option (which I assume could be accessed using .withOption( 'preDrawCallback', ... ); in the Angular DataTables integration.

    That will be called before DataTables updates the display, so you have the option to remove events from the existing elements before they are removed.

    Allan

  • phawellphawell Posts: 28Questions: 12Answers: 1

    I'm going to use it right now.

    Some suggestion for most effective executions to eliminate I Would execute in that function.

    I want delete every DOM node of olds rows.

    I'm loading and refreshing with ajax so I do not want to delete the datatable object just the old ROWS DOM and listeners.

    I'm using this:

               dtInstance_obj.DataTable.rows().nodes().to$().off('*');
               dtInstance_obj.DataTable.clear();
               dtInstance_obj.DataTable.clear();
    

    Do you think something is missing?

    Thank you very much for your patience

  • allanallan Posts: 63,464Questions: 1Answers: 10,466 Site admin

    I don't believe you should need to use clear(). Just removing the event listeners should do it, assuming that is what the problem was.

    Allan

  • phawellphawell Posts: 28Questions: 12Answers: 1

    One more doubt. I have noticed that it throws twice the preDrawCallback method when the data is reloaded.

    1) The first time before calling **createdRow **and I use this to clean up of events each old ROW

    2) Then launch **createdRow **for every new ROW and new rows are painted.

    3) But in the end launches again **preDrawCallback ** and this is where I delete the events so this time is deleted the last new rows drawn, which is not what we want.

    Is there a method that is called only once before drawing each ROW? Or just some trick for this **preDrawCallback **to run only once.

    Thanks, I appreciate your help very much.

  • allanallan Posts: 63,464Questions: 1Answers: 10,466 Site admin

    I have noticed that it throws twice the preDrawCallback method when the data is reloaded.

    Yes, a reload will clear out the existing rows first (depending on the exact configuration / API calls being made).

    If you just remove all events in that callback, it should be fast and safe.

    Allan

This discussion has been closed.