Slow Performance on creating multiple Datatable instances on a page
Slow Performance on creating multiple Datatable instances on a page
I am currently doing a NodeJS
project and the front-end is using Pug + JQuery + Datatable + Bootstrap 4
to render the pages.
Currently there is a page where I will create lots of Datatables ( ~450) on it, each with about 10 rows, and I am doing it using client-side processing. It comes to my attention that when the page loads really slow. In Chrome, it takes about 8-9 seconds for tables to be fully loaded, which is no good since it will freeze that page for 8-9 seconds
I have been searching through the forum and using some of the suggested answers like enabling the deferRender
and enabling paging
. However, those don't really work on my case
Basically what I am doing right now is: using Pug
, I am creating the page with 450 tables using a for-loop, in which each table is created and data is passed from the server-side using the render(view, locals)
of ExpressJS
. The client side will use a JS script which simply do the JQuery Datatable initialization stuff
Pug Code Snippet:
page1.pug
each table in tableData //- you can think it as a for-each loop, which will iterate and create same table 450 times on the page
table.table.table-hover.table-striped.table-bordered.hafanTable(style="width:100%")
caption
.card.text-white.mb-3.text-center.hafanCaption #{table.caption}
thead
tr
th Brand
th Total
th Successful
th Failed
tbody
each row in table //- each table has around 10 rows
tr
td #{row.brand}
td #{row.total}
td #{row.success}
td #{row.failed}
JQuery:
$('.hafanTable').DataTable({
ordering: false,
deferRender: true,
paging: true,
orderClasses: false,
initComplete: function (setting, json) {
$('.scrollspy-example').css('height', Math.max($('.dataTables_wrapper').height(),
$('ul.nav').height()) + 'px');
}
});
server-side app.js
(Node)
app.route('/page1').get((req, res) => {
res.render('page1.pug', { data });
...
Data passed to Pug to be parsed
[{
"caption": "table 1",
"brand": "apple",
"total": "10",
"success": "9",
"failed": "1"
},
{
"caption": "table 2",
"brand": "coca",
"total": "5",
"success": "5",
"failed": "0"
},
{
"caption": "table 3",
"brand": "orange",
"total": "8",
"success": "6",
"failed": "2"
},
{
"caption": "table 4",
"brand": "pine",
"total": "10",
"success": "9",
"failed": "1"
},
... about 400 more objects like this
]
I haven stuck on this performance issue for a while, tried the previous solution on the forum but unfortunately they don't work for my case. So I decide to ask by myself and any help will be appreciated
This question has an accepted answers - jump to answer
Answers
One thing I would look at doing is using
rows.add()
to add your data to the initialized Datatables instead of the for loop you have. Might help increase the speed, not sure.You are right the
deferRender
is going to help since you have only 10 rows per table and by default each Datatable displays 10 rows.It seems there are three areas to look at. Is the delay with the ajax request/response, the pug for loop or the init of 450 Datatables.
Kevin
@kthorngren thanks for the quick reply. Regarding the jquery I am not sure if I am initializing the tables in the way I posted above, is it going to be sequential? i.e. the later Datatables have to wait until the previous Datatable is fully initialized?
Is there any better to initialize a large number of Datatables in JQuery?
I'm not sure. The Developer (Allan) will help with that answer.
Is your 4500 records (450 x 10) returned in one ajax or multiple?
Maybe you can use some console.log outputs to see how long various areas take. Might be interesting to see the time difference with the tables populated using the for loop and blank tables.
Kevin
I just change one line of code in JQuery and it surprisingly makes the whole loading becomes much faster. But I am not understanding why
In Pug, when I create the wrapper div for the table, I will include them in them in a customized class, using my username
hafan
where
.xxx
is just Pug's shortcut to add a class to a divand I used to select by that class
hafanTable
in JQueryhowever, when I change to selector to
.dataTables_wrapper
The loading speed suddenly increased from 7s to 3s !? I am not understanding what is happening behind the scene. Is
dataTables_wrapper
automatically created by Bootstrap or DataTable API?Hi @hafan ,
Yep,
dataTables_wrapper
is a container created by DataTables when the table is initialised, so I'm surprised$('.dataTables_wrapper').DataTable({...})
works - the class shouldn't exist before that initialisation, so shouldn't be usable for the initialisation! It suggests that the table is being initialised prior to that line of code being called!Cheers,
Colin
Correct. Javascript is single threaded, so it has to be sequential. This is the loop that makes it run in order - its just looping over the nodes jQuery has selected.
@hafan - If you could link to a page showing the issue that would be really useful so we can profile it.
Allan
Hi @allan I believe all code relevant to my question has been posted above, but I am happy to re-explain the problem I have met to make things look more clear to you
HTML(Pug)
In the HTML (Pug), I repeat the tasks of creating the wrapper divs for placing the datatable under a for loop
As you can see, I add a customized class
hafanTable
to all these wrapper divsand tableData will be passed from server and Pug will parse it during the rendering. It is just a regular JS object:
So once the DOM has been fully loaded, data for each table should already be populated and I think probably datatable only need to read these data to support client-side search and ordering?
Lastly, as I've created the wrappers and I believe I only need to initialize datatables inside them through a client-side script which simply use JQuery
where as you can, I select the wrappers by using the customized class attached to them in Pug, the
hafanTable
The trick (although I still don't understand it), when I change the selector, to use
dataTables_wrapper
instead. It works perfectly and even boost the load speed from 7-8 seconds to 3 secondsYep, it would help us though if you could link to a test case with instructions on how to reproduce. Information on how to create a test case (if you aren't able to link to the page you are working on) is available here.
Cheers,
Colin