Global Filter function hangs in IE

Global Filter function hangs in IE

bryceray1121bryceray1121 Posts: 65Questions: 0Answers: 0
edited November 2010 in General
I've developed a global filter for my tables. This filter will take input from a user then search all the tables on the page filtering them to the user input. This function is mostly working properly in all browsers. Two main problems exist.

1) In firefox when I search via this method the search term is automatically entered into each individual tables filter box. However, in IE the term is only entered into the first tables filter input. All tables filter but only one will list the filter text so it may become confusing to the user.
2)The search function is acceptably quick in firefox. In IE, the search hangs (often prompting a slow script dialogue from the browser). The script eventually completes. The problem is the process gives the illusion of a frozen browser.

My test group:
I'm using a decent sized test group of 12 tables with any where from 1-30 rows. About 1/4 of the tables are completely empty.

The code I have right now:
[code]
function globalSearch(value){
if(value == null) value = document.getElementById("searchInput").value;
for(var i=0;i<(oTable.length);i++){
$.fn.dataTableExt.iApiIndex = i;
if((oTable.fnGetNodes( ).length) > 0){
oTable.fnFilter(value);
}
}
$.fn.dataTableExt.iApiIndex = 0;
}
[/code]

This code is pretty straight forward. The only performance adjustment I could think to add was skipping empty tables. This does provide a significant performance improvement if your environment is likely to have a few empty tables.

Can anyone provide any suggestions on:
1). Improvements I can make to this function to improve the overall performance?
2). Improvements I can make to specifically improve performance in IE?

Replies

  • bryceray1121bryceray1121 Posts: 65Questions: 0Answers: 0
    edited November 2010
    I did some benchmarking to measure exactly how much of a difference there was. Here are my results (table number: time in milliseconds):
    [code]
    FireFox
    table 0: 75, table 1: 49, table 3: 54, table 4: 52, table 6: 62, table 9: 101, table 10: 64, table 11: 50, table 12: 53, table 13: 57
    table 0: 51, table 1: 47, table 3: 51, table 4: 51, table 6: 47, table 9: 51, table 10: 60, table 11: 49, table 12: 58, table 13: 49
    table 0: 48, table 1: 53, table 3: 51, table 4: 51, table 6: 48, table 9: 51, table 10: 68, table 11: 49, table 12: 51, table 13: 49

    IE8
    table 0: 62, table 1: 35, table 3: 43, table 4: 44, table 6: 39, table 9: 46, table 10: 57, table 11: 33, table 12: 24, table 13: 34
    table 0: 55, table 1: 58, table 3: 45, table 4: 45, table 6: 35, table 9: 65, table 10: 76, table 11: 26, table 12: 27, table 13: 40
    table 0: 53, table 1: 35, table 3: 55, table 4: 54, table 6: 39, table 9: 41, table 10: 52, table 11: 22, table 12: 24, table 13: 31


    IE7
    table 0: 488, table 1: 969, table 3: 965, table 4: 952, table 6: 917, table 9: 924, table 10: 1211, table 11: 15317, table 12: 39599, table 13: 3845
    table 0: 550, table 1: 965, table 3: 972, table 4: 957, table 6: 924, table 9: 944, table 10: 1225, table 11: 15393, table 12: 38994, table 13: 3925
    table 0: 529, table 1: 981, table 3: 965, table 4: 978, table 6: 959, table 9: 963, table 10: 1218, table 11: 15570, table 12: 39611, table 13: 3798
    [/code]

    This is the function I used with the benchmarking elements in it:
    [code]
    function globalSearch(value) {
    var loTable = oTable;
    if ((value === undefined) || (value === null)) {
    value = document.getElementById("searchInput").value;
    }
    var executionTime = "";
    for (var i=0;i < (loTable.length);i++) {
    $.fn.dataTableExt.iApiIndex = i;
    if ((loTable.fnGetNodes( ).length) > 0) {
    var start = new Date().getTime();
    loTable.fnFilter(value);
    var stop = new Date().getTime();
    executionTime += ", table "+i+": "+ (stop - start);
    }
    }
    alert(executionTime);
    $.fn.dataTableExt.iApiIndex = 0;
    }
    [/code]

    Each test was run using the same search term on the same data on the same number of tables. You will notice some table elements are skipped, this is because they are empty tables.

    This is a pretty sizable difference in fnFilters execution. Any ideas on what might be causing this?
  • allanallan Posts: 63,281Questions: 1Answers: 10,425 Site admin
    >This is a pretty sizable difference in fnFilters execution. Any ideas on what might be causing this?

    Yeah - the IE7 JS engine :-). I'm afraid it looks like you are simply hitting a performance issue with the IE7 engine which is well known to be horribly slow. It's a nice idea to skip over empty tables and your code is very similar to the fnFilterAll API plug-in: http://datatables.net/plug-ins/api#fnFilterAll

    You could try disabling a few features and see if that helps in IE7. Specifically bSortClasses will likely make a difference ( http://datatables.net/faqs#speed ) and I would think that sorting will as well.

    Beyond that, I think it's time to start looking at a profiler to see where speedups could be made specifically for IE7.

    Allan
  • bryceray1121bryceray1121 Posts: 65Questions: 0Answers: 0
    edited November 2010
    I put togeather a small function to test this. I'm not sure how the search function works in data tables and I'm sure its much more complex.

    I loaded all of my html tables in to a test html document. Added a search input and button and ran this function. The function is not perfect or tested that much but it performs a basic filter on all the tables.
    [code]

    function search(){
    var value = document.getElementById('inputText').value;
    var table = getElementsByClassName("dataTable")
    for(var x=0;x
  • bryceray1121bryceray1121 Posts: 65Questions: 0Answers: 0
    It appears as if the change I made for my other support thread (default sort columns) has fixed this problem. After I changed the way data tables were initialized for the default sort columns I had to go back and adjust my global search function. I'm assumign this was because iApiIndex was not relevant since oTable is now an array. Now I'm using this global search function:
    [code]
    function globalSearch(value) {
    var loTable = oTable;
    if ((value === undefined) || (value === null)) {
    value = jQuery("#searchInput").val();
    }
    for (var i=0;i < (loTable.length);i++) {
    if ((loTable[i].fnGetNodes( ).length) > 0) {
    loTable[i].fnFilter(value);
    }
    }
    }
    [/code]

    I tested this in IE7 (firefox, IE8, etc) and I am now seeing more appropriate search execution times. I'm not sure what the root cause of this problem was but it is fixed now.
  • allanallan Posts: 63,281Questions: 1Answers: 10,425 Site admin
    Hi bryceray1121,

    Nice one - excellent to hear that this is sorted! I would have thought that if anything would go funny with iApiIndex it would simply cause a JS error, rather than taking a long time. However, as long as it works now... :-)

    Regards,
    Allan
  • bryceray1121bryceray1121 Posts: 65Questions: 0Answers: 0
    I know this is an old post but I am still using the same code and am again experiencing performance problems with IE. The problem now is slightly different. I have multiple data tables on a single page and I have create a global filter input which filters all tables. This works in all browsers except IE where the process seems too slow and I get a slow script timeout message from IE.

    I've noticed that the error only occurs when I pass an empty value to fnFilter "". For example consider this data set of timings:
    [quote]9-15
    12-13
    9-25
    9-26
    8-29
    12-568
    89-1651
    50-132
    15-23
    10-24
    8-19
    17-27
    12-21
    14-21
    29-37[/quote]

    Each row of these timings represents a individual table on the page. The first number represents the time required for the table to filter the word "high". As you can see the timings are in a respectable range. The second number, after the dash, is the time required to reset the filter to its original state. I do this by passing an empty value to fnFilter(""). As you can see some tables have significantly higher values when I am "resetting" the filter. It is also important to note that the time scale to the number of rows in the table. So the table 89--1651 has more rows than the table 12-13.

    I also get higher timings if I first filter "high" then filter just "hi". I think the main problem has to do with the timing to add a row back to the table.

    I created the timing by inserting this code to the data tables library in this.fnFilter:
    [code]
    if ( iColumn === undefined || iColumn === null )
    {
    var start = new Date().getTime();
    /* Global filter */
    _fnFilterComplete( oSettings, {
    "sSearch":sInput+"",
    "bRegex": bRegex,
    "bSmart": bSmart,
    "bCaseInsensitive": bCaseInsensitive
    }, 1 );

    if ( bShowGlobal && oSettings.aanFeatures.f )
    {
    var n = oSettings.aanFeatures.f;
    for ( var i=0, iLen=n.length ; i
  • allanallan Posts: 63,281Questions: 1Answers: 10,425 Site admin
    Can you link me to your page or run it through the debugger so I can see your configuration setup please (a link would be best in this case)?

    DataTables' filtering does to optimisation such that smaller filtering sets will run faster and a filter gets more selective - which I suspect will explain the timing differences. But it will be interesting to see if the filtering as a whole can be speed up for you (although I'm not sure how, or I would have done it by now :-) ).

    Allan
This discussion has been closed.