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?
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...
- Version 1 (see code), deferRender = true : 332 calls
- Version 2 (see code), deferRender = true : 232 calls
- 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
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
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
Without deferRender the results are this:
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
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:
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.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
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 somehowdeferRender
. 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.
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