DataTables and SocketIO Streaming

DataTables and SocketIO Streaming

jtomaszejtomasze Posts: 8Questions: 0Answers: 0
edited April 2014 in General
Hello - Looking for some help or recommendation(s). I have an implementation where I use socketio to retrieve JSON results from a web service and want to stream these results to the datatable. Each result from the web service equates to one new row in the table. Almost like a real-time stock ticker. I have pasted my code below. It does work, this is not a question about getting it to work. My issue is performance. I've tried in IE, FF, Chrome and Safari. IE by far is the slowest and when even trying to stream 100 results to the DOM the web page completely hangs and becomes unresponsive. It looks like to me that the page is redrawing each time I add a new row of data to the table. The results come in so fast from the web service that the web page is playing catch up with each row I add. That is my theory.

With all that said maybe it is my execution with the code and how I am doing and not datatables itself. Actually I am almost certain. Can anyone take a look at the code below and provide a better suggestion? For every new row of data I get from the web service I call fnAddData. Maybe that's not the best way. I've tried with pagination on and off and the results are the same.

Thanks in advance.

[code]
<!DOCTYPE html>








var dataT;
var tempArray;
function streamResults(){



var aoColumns = [
{ "sTitle": "Title" }
];

$('#results').dataTable({
"bProcessing": true,
"aoColumns": aoColumns,
"bSort": false,
"bSortClasses": false,
"bDeferRender": true,
"iDisplayLength": 25,
"bLengthChange": false,
"bPaginate": true,
"oLanguage": { "sZeroRecords": "No Results Found" },
"bFilter": false,
"bDestroy": true
});
dataT = $('#results').dataTable();


var socket = io.connect("http://xxxx/getJSON");
socket.on("result", handle_result);
socket.emit("message", 100);
}

function handle_result(data) {
var be_response = JSON.parse(data);
processSearchResultsStream(be_response);
}

function processSearchResultsStream(data) {
if (data.body.object == undefined) {
return;
}
else {
var stuff= data['body']['stuff'];
tempArray = new Array(stuff);
dataT.fnAddData(tempArray);
}
}







[/code]

Replies

  • allanallan Posts: 63,498Questions: 1Answers: 10,470 Site admin
    edited April 2014
    > "bDestroy": true

    Oof! You are destroying and recreating the table for every new row? Yup - that's going to kill performance!

    Why not just add the new row using the API? Then you don't need to destroy and recreate the table every time!

    *edit* I might have misunderstood your code - sorry. I think you can probably disregard what I've said above...

    How fast are the results coming in? If you are doing fnAddData very quickly you would be better off putting a debounce in, so it will do a single draw, every 1 second (for example).

    Allan
  • jtomaszejtomasze Posts: 8Questions: 0Answers: 0
    Forgot to mention. I am using DataTables 1.9.4.
  • jtomaszejtomasze Posts: 8Questions: 0Answers: 0
    That was a bad copy/paste. That line of code is actually commented out on my side here. Sorry, I was modifying my code before I posted here so individuals would not see server names and things.

    [code]
    $('#results').dataTable({
    "bProcessing": true,
    //"aaData": _gridResults,
    "aoColumns": aoColumns,
    //"aaSorting": [[2, "asc"]],
    "bSort": false,
    "bSortClasses": false,
    "bDeferRender": true,
    "iDisplayLength": 25,
    "bLengthChange": false,
    "bPaginate": true, //keep pagination on; if we disable it, it will display all results at once and we don't want this!
    "oLanguage": { "sZeroRecords": "No Results Found" },
    "bFilter": false,
    //"bDestroy": true
    });
    [/code]
  • jtomaszejtomasze Posts: 8Questions: 0Answers: 0
    edited April 2014
    I am using the API for each new row; fnAddData. Or am I missing your point?

    [code]
    function processSearchResultsStream(data) {
    if (data.body.object == undefined) {
    return;
    }
    else {
    var stuff= data['body']['stuff'];
    tempArray = new Array(stuff);
    dataT.fnAddData(tempArray);
    }
    }
    [/code]
  • allanallan Posts: 63,498Questions: 1Answers: 10,470 Site admin
    You are - I miss read the code (see my edit).
  • jtomaszejtomasze Posts: 8Questions: 0Answers: 0
    edited April 2014
    No problem at all. Thank you very much for your quick responses. At times I can get more than 5 results come in less than one second, so fast. Client side pagination being enabled or disabled would not alleviate this issue, correct? Because with either way, on the client, the DOM still has to handle all the results? The client side pagination simply provides a mechanism to "chunk up" the results for viewing but the page is still being forced to process all the results coming back. I just want to confirm this.

    debounce, are you referring to the jQuery throttle mechanism $.debounce? My quick web search finds this: http://benalman.com/projects/jquery-throttle-debounce-plugin/

    *OK, not jQuery. Looks like a custom library that this gentleman put together.
  • allanallan Posts: 63,498Questions: 1Answers: 10,470 Site admin
    > Client side pagination being enabled or disabled would not alleviate this issue, correct?

    A little, but not much.

    Debounce - sorry, yes, it should have said throttle, they are slightly different. Basically you want a little timer that is started when you do your fnAddData (with the second parameter as `false` to prevent the draw) and is reset when there is a new fnAddData call made. After a timeout it will trigger the fnDraw call.

    Allan
This discussion has been closed.