How to reduce no. of render function for display? Is deferRender not working properly in my case?

How to reduce no. of render function for display? Is deferRender not working properly in my case?

edwardcedwardc Posts: 30Questions: 11Answers: 0
edited July 2018 in General

One of my column use render: function to add a flag next to the name. This create a performance problem when the function is called too many times.
I counted how many times the function is called, after adding filters for "sort" and "type" and leave only "display". Note that I do use deferRender = true by default, I tested without it only for reference.

Here are my results for 2 tables, each containing 50 rows, pageLength being set to 15:
I was expecting to be called 2 tables X 15 rows each = 30 times. Instead...

  1. Version 1 (see code), deferRender = true : 332 calls
  2. Version 2 (see code), deferRender = true : 232 calls
  3. Version 2 (see code), deferRender = false : 300 calls (for testing only, reduced with 68 so it's working... sort of...)

Here is the code for the render function:

let formatCountry = function (data, type, row) {
    // if (type === "sort" || type === 'type') // version 1
            if (type !== "display") // version 2
        return data;
    else {
        wasCalled++; // counting var
        let flagImg = "<img class = 'flag-border' src='" + path_to_flags + row.cnt_iso3 + ".svg' alt = '" + row.cnt_iso3 + "' title='" + row.cnt + "' />";
        return flagImg + data;
    }
};

And here is the code for dt:

$(tableId).DataTable({
        data          : dataSource,
        deferRender: true,
        pageLength: 15,
        lengthMenu: [ 15, 30, 50, 100 ],
        columns     : [
            {
                title: "something",
                data : 'something',
                render: formatCountry
            },
//.... some other columns
});

Also I have default initialization for all datatables:

$.extend($.fn.dataTable.defaults, {
    responsive: true,
    select: false,
    lengthChange: true,
    searching: true,
    ordering: true,
    deferRender: true, // default!
    dom: '...something....',
    language: {
                //.... something....
         }
}

How can I get to 30 calls to rendering function? Or, to be more precise, filter all the calls to attach the img only to the visible rows?
Note: I have pages using tables but I used this one as an example. Another page with 239+211 rows calls render 2310 times and this is painful. About 1sec delay. This table also use scrollX so I thought it may affect the outcome but the problem is also with the example I give, where setup is more clear.

So? What am I missing/doing wrong? How can I filter the calls so that I add the flag only to the visible columns?

Answers

  • colincolin Posts: 15,240Questions: 1Answers: 2,599

    Hi @edwardc ,

    I just tried it here, and I'm only seeing the rendered function count go up each time the visible columns are drawn - so in chunks of 10 (single column calling the render function, and 10 rows per page). It goes up continuously because serverSide is enabled so the client's cache isn't being used.

    I'm not sure why yours would be going up so much more - would you be able to modify my test case, or create your own, so that we can see the problem, please.

    Cheers,

    Colin

  • kthorngrenkthorngren Posts: 21,443Questions: 26Answers: 4,974
    edited July 2018

    I updated Colin's example to remove server side and use deferRender to show the behavior. The example has the below results:

    http://live.datatables.net/wuyapuca/1/edit

    57 type
    57 sort
    57 filter
    10 display  << deferRender
    57 display  << not sure what is going on here
    display       << nor this single 
    COUNT: 239
    

    Without deferRender the results are this:

    57 display
    57 type
    57 sort
    57 filter
    57 display
    COUNT: 285
    

    Not sure why, with deferRender, there are those last display deferRender functions executions. Maybe @allan can explain why and what is happening.

    I'm not sure how your numbers occurred. They seem high by about 100 but its possible there is something causing an extra trip through the render function that my example doesn't.

    Kevin

  • allanallan Posts: 63,680Questions: 1Answers: 10,498 Site admin

    The rendering function can be called for any cell at any time - regardless of whether it needs to be rendered or not. Consider for example sorting, DataTables needs to get the data to sort for all cells in the sorting column so it can decide what rows (cells) should be displayed! Likewise with filtering.

    The display option should be called when the cell is created. That will happen if it needs to be displayed and the data was loaded into the table via Javascript (e.g. Ajax).

    The console data Kevin shows is correct:

    57 display << not sure what is going on here

    This is due to the autoWidth feature. DataTables needs to get the data for the cells in order to be able to optimise the width.

    display << nor this single

    This is an odd one. It appears to be coming from the width calculation as well, but I'm not sure why it is shown separately!

    So long story short - it is working as expected. Don't do anything in a rendering function that takes more than a few microseconds to complete.

    Allan

  • edwardcedwardc Posts: 30Questions: 11Answers: 0
    edited July 2018

    Hi all, hi Allan, thanks for help.
    Indeed, it is not server-side. I work with json's.
    Meanwhile I found : this discussion. I set autoWidth to false and the numbers are totally different now:
    With 'autoWidth: false,' the page with pagination set at 15, called the render function 15 times! Iuhuu victory!
    Another page with scrollX called once for each cell, disregarding somehow deferRender. I will keep digging, for the time being I'm fine with the results.

    Allan, you are right and I do all the heavy computing on the server where I create the json but attaching an small img (flag) have a great visual impact so I have to keep it. The inevitable bad part is that this delay occurs on page-load, specialy where the img(flags) are not cached yet. After page load I don't have a big issue with the rendering speed + cached img = milliseconds so not a problem.

  • allanallan Posts: 63,680Questions: 1Answers: 10,498 Site admin

    With 'autoWidth: false,' the page with pagination set at 15, called the render function 15 times! Iuhuu victory!

    Yup. The downside of course is that it now doesn't have the auto width calculations :). But depending on your table that might not be much of an issue for you.

    Allan

This discussion has been closed.