Memory leak issues with Datatable

Memory leak issues with Datatable

moneyplantmoneyplant Posts: 3Questions: 1Answers: 0

We use DataTable to display upto 5000 records in the browser. And every time user triggers search, a fresh search query is triggered and a new set of 5000 records are shown to the user. Now the issue here is, by the time user triggers search for the 3rd or 4th time, it crashes the browser. Looking at the JS Heap Size in memory tab of the dev tools shows that every time a search is triggered, the total heap size keeps increasing. Currently using version - 1.10.16. I have tried .clear(), .destroy() api's before updating the table with new set of data, but these don't seem to make any difference and the issue still persists.

Am I missing something trivial in terms of implementation here. Any help would be helpful.

Following is the code that I have used to display the data:

if(table != null){
    table.clear();
}

table = $('#uniqueTable').DataTable({
    data: richData,
    columns: columnData,
    deferRender: false,
    lengthMenu: [[10, 25, 50, 100, 250], [10, 25, 50, 100, 250]],
    bDestroy: true,
    select: {
        style: 'multi',
        selector: 'td:first-child input'
    },
    stateSave: true,
    stateSaveCallback: function (settings, data) {},
    stateLoadCallback: function (settings) {}
});

This question has an accepted answers - jump to answer

Answers

  • kthorngrenkthorngren Posts: 20,292Questions: 26Answers: 4,768
    edited May 2023

    I've never heard of Datatables having a memory leak. Not saying it doesn't but you aren't doing anything out of the ordinary.

    However if you aren't changing the Datatables configuration then it might be more efficient to not use destroy and use clear() and rows.add() to update the table data. Maybe like this:

    if(table != null){
        table.clear();
        table.rows.add( richData ).draw();
    } else {
     
        table = $('#uniqueTable').DataTable({
            data: richData,
            columns: columnData,
            deferRender: false,
            lengthMenu: [[10, 25, 50, 100, 250], [10, 25, 50, 100, 250]],
            select: {
                style: 'multi',
                selector: 'td:first-child input'
            },
            stateSave: true,
            stateSaveCallback: function (settings, data) {},
            stateLoadCallback: function (settings) {}
        });
    }
    

    How are you loading the data and building the richData variable?

    Can you post a link to your page or a test case replicating the issue so we can take a look?
    https://datatables.net/manual/tech-notes/10#How-to-provide-a-test-case

    Kevin

  • kthorngrenkthorngren Posts: 20,292Questions: 26Answers: 4,768

    Just to add you can use DataTable.isDataTable() to check if the Datatable has been initialized.

    Kevin

  • allanallan Posts: 61,692Questions: 1Answers: 10,101 Site admin

    Also, update. 1.10.16 is old (2017) and a bunch of stuff has been fixed since then, possibly including memory leaks (I can't recall off the top of my head!).

    Allan

  • moneyplantmoneyplant Posts: 3Questions: 1Answers: 0

    I tried the above suggestions, but I still see that the heap memory size keeps increasing after every search.

    I took a heap snapshot after performing search for the first time, and searched again and took another snapshot of the heap. On doing comparison, following is the result I get

  • allanallan Posts: 61,692Questions: 1Answers: 10,101 Site admin

    Happy to take a look at a test case showing the issue so I can debug it.

    Allan

  • moneyplantmoneyplant Posts: 3Questions: 1Answers: 0

    Hi, following is an example of how we are using datatable in our code. Clicking on Search button here simulates a search request to the backend. https://live.datatables.net/temexasa/1/edit

  • allanallan Posts: 61,692Questions: 1Answers: 10,101 Site admin
    Answer ✓

    There was one event handler that I had missed and it wasn't removing, resulting in a small leak. I've committed a fix for that.

    However, you can side step that issue completely by not destroying the table each time, just add the new rows using the API. Also, enable deferRender which will massively improve performance for you. Your example is crashing Chrome for me due to the number of cells in the table.

    Here is the example updated with those changes.

    Allan

  • YokomokoYokomoko Posts: 7Questions: 1Answers: 0
    edited May 2023

    Just wanted to throw my hat in the ring, too. We've got a rather complicated DataTable where we're filling a table and then throwing datatables over the top (due to the complex nature of populating said table). When we refresh the grid it clears that entire table, destroys DataTable, populates the table and throws DataTable over the top again.

    I believe I've made the change that Allan has checked into the source code manually, and the issue still occurs. Every refresh, the ram usage seems to drop slightly (presumably from clearing said 1000 rows), and then levels off 50-100mb larger. For further context we're using the latest version of CefSharp.WinForms, but the issue still happens in Chrome as well.

    Oddly, Edge (Chromium version) appears to be absolutely fine and trundles along with no problem (Unless there's some MSFT trickery going on here and it's offloading that usage to another process).

    Due to the way we're rendering DataTable, I do not believe we could use deferRender?

    Further context of complication:
    The columns, and column orders can be different for each user. We're adding custom attributes to each row based on the data of that row, setting colspans on certain rows if the column order is our default, having hidden rows for sorting, and custom sorting on other rows.

  • allanallan Posts: 61,692Questions: 1Answers: 10,101 Site admin

    I've just tried the example I updated yesterday with the latest change in DataTables and it does appear to have solve the little leak that was present (it wasn't massive, but was still present).

    The best way I've found to identify leaks is the Chrome "Allocation instrumentation on timeline" option in the "Memory" inspector. Start the page and then start recording that option - perform the action that the leak appears in. This is an example from the updated example, where the spike is where I clicked the "Search" button:

    Blue areas of the spike are memory still used. Grey is memory that was allocated and can now be freed by the browser (it might not actually do so until later though!). The area I've highlighted shows there is no retained elements / objects from the table creation, i.e. no leak. The compiled code is what Chrome has decided to optimise (based on whatever heuristics they use!). The blue bar at the end is the current DataTable with the memory needed for it.

    I'm confident that in that table, there is no leak now.

    @Yokomoko - If you can link to a page showing the issue, I can take a look.

    Keep in mind that just because DataTables has released objects, Chrome might not actually free them from system RAM - garbage collection takes time, and it might keep a hold of what RAM is has already requested, in order that it can allocate it again. Garbage collection is probably tuned differently between Chrome and Edge, which might explain the issue.

    Due to the way we're rendering DataTable, I do not believe we could use deferRender?

    It is rare that deferRender can't be used, but I'd need to see a test case to know for sure.

    Allan

Sign In or Register to comment.