IE Speed.
IE Speed.
I am using datatables plugin using the option of passing all my data rows as an array. I let datatables handle the filtering and sorting. Everything was fine until a user complained that it was slowing down the page loads. The user with the problem is using IE. I have tested the page(s) that use the plugin in IE, Chrome, Firefox and Safari. IE was the only one with a performance issue.
The effect on IE is exaggerated because it hangs the whole page until it is finished processing. Chrome, Firefox and Safari do not seem to have a big impact on the page.
I used the profiler option of the debugging tool. The time was spent in calls to jQuery's css routine. The plugin makes a lot of calls to css especially if sScrollX or sScrollY is specified.
I realize that loading all the data rows makes the plugin create all the table rows even if only a small part are actually displayed.
I still did not want to move the sorting and filtering to the server. So instead I made dataTables think I was doing server side processing but implemented it as a function. The data is still completely downloaded via an xhr request, but only on first loading, if the user asks for a refresh, or on a timer. The server side function does the filtering, sorting and selecting of current page rows.
The performance on IE was dramatic. For around 2500 rows of data (about 9 columns) It took around 15 to 20 seconds before the change. After it went down to less than 2 seconds.
Any way that is my story and the reason I really really do not like to use IE. Although the profiler in IE debugger was very impressive. I suggest it to anybody with performance problems.
Cheers!
The effect on IE is exaggerated because it hangs the whole page until it is finished processing. Chrome, Firefox and Safari do not seem to have a big impact on the page.
I used the profiler option of the debugging tool. The time was spent in calls to jQuery's css routine. The plugin makes a lot of calls to css especially if sScrollX or sScrollY is specified.
I realize that loading all the data rows makes the plugin create all the table rows even if only a small part are actually displayed.
I still did not want to move the sorting and filtering to the server. So instead I made dataTables think I was doing server side processing but implemented it as a function. The data is still completely downloaded via an xhr request, but only on first loading, if the user asks for a refresh, or on a timer. The server side function does the filtering, sorting and selecting of current page rows.
The performance on IE was dramatic. For around 2500 rows of data (about 9 columns) It took around 15 to 20 seconds before the change. After it went down to less than 2 seconds.
Any way that is my story and the reason I really really do not like to use IE. Although the profiler in IE debugger was very impressive. I suggest it to anybody with performance problems.
Cheers!
This discussion has been closed.
Replies
Allan
For UPEngineer, Following is some of the code. When these functions are executed the object self.fullData as all the data already down loaded from the server:
This snippet creates the options object passed to datatables.:
[code]
var dataTable_options = {
sScrollX: '100%',
bAutoWidth: false,
bJQueryUI: true,
bInfo: true,
bProcessing: true,
sPaginationType: "full_numbers",
aLengthMenu: [[5, 10, 15, 20, 50, -1], [5, 10, 15, 20, 50, "All"]],
iDisplayLength: 20,
// aaData: data[myOptions.sViewName + 's'],
aaSorting: [[1, 'asc']],
oLanguage: { sEmptyTable: "No Available " + myOptions.sViewName + "s" },
aoColumnDefs: suppressSortOnUnaryColumns(),
fnDrawCallback: function () {
jQuery(window).scrollLeft(jQuery(document).width() - jQuery(window).width());
reOpenSavedNodes();
}
};
if (myOptions.bUseServerSide) {
dataTable_options.bServerSide = true;
dataTable_options.fnServerData = fnServerSideProcessing;
} else {
dataTable_options.bDeferRender = true;
dataTable_options.aaData = self.fullData;
};
[/code]
This snippet is the function that is the fnServerData option:
[code]
function fnServerSideProcessing(sSource, aoDataIn, fnCallback) {
var aoData = {};
for (ind = 0; ind < aoDataIn.length; ind++) {
aoData[aoDataIn[ind].name] = aoDataIn[ind].value;
};
self.compiledData.aaData = []; // set of data after filtering
self.compiledData.sEcho = aoData.sEcho;
self.compiledData.iTotalDisplayRecords = 0;
var iDisplayed = 0;
var colRegex = {};
var noSearches = false;
for (var ind = 0; ind < self.fullData.length; ind++) { // scan data saving rows in aaData that pass filters!
var row = self.fullData[ind];
var found = true;
if (!noSearches) {
noSearches = true;
for (var colind = 0; colind < aoData.iColumns; colind++) {
var sSearch = aoData["sSearch_" + colind.toString()];
var colName = aoData["mDataProp_" + colind.toString()];
if (aoData["bSearchable_" + colind.toString()] && sSearch !== '') {
noSearches = false;
if (aoData["bRegex_" + colind.toString()]) {
if (typeof colRegex[colName] === "undefined") colRegex[colName] = new RegExp(sSearch, '');
if (!colRegex[colName].test(row[colName])) {
found = false;
break;
};
} else {
if (row[colName] !== sSearch) {
found = false;
break;
};
};
}
};
};
if (found) {
self.compiledData.iTotalDisplayRecords += 1;
//if (self.compiledData.iTotalDisplayRecords >= aoData.iDisplayStart) {
// iDisplayed += 1;
// if (iDisplayed <= aoData.iDisplayLength) {
self.compiledData.aaData.push(row);
// };
//};
};
};
self.compiledData.aaData.sort(function (o1, o2) { /sort the filtered rows!
var sSortCol, returnLessthan, v1, v2;
for (ind = 0; ind < aoData.iSortingCols; ind++) {
sSortCol = aoData["mDataProp_" + aoData["iSortCol_" + ind.toString()].toString()];
switch (aoData["sSortDir_" + ind.toString()]) {
case "asc":
returnLessthan = -1;
break;
case "desc":
returnLessthan = 1;
break;
default:
returnLessthan = -1;
};
v1 = o1[sSortCol];
v2 = o2[sSortCol];
if (v1 === null) {
if (v2 !== null) return returnLessthan;
} else {
if (v2 === null) {
return 0 - returnLessthan;
} else { // v1 and v2 are not null!
if (v1 < v2) {
return returnLessthan
} else {
if (v1 > v2) return 0 - returnLessthan;
};
};
};
};
return 0;
});
self.compiledData.aaData.splice(0, aoData.iDisplayStart - 1); // remove those rows before page start!
self.compiledData.aaData.splice(aoData.iDisplayLength, self.compiledData.aaData.length - aoData.iDisplayLength); // remove rows after page end!!
fnCallback(self.compiledData); // send data back to dataTables!
};
[/code]
Cheers!