How to speed up the reading of innerHTML in IE8?
Asked Answered
G

5

7

I am using JQuery with the DataTable plugin, and now I have a big performnce issue on the following line.

aLocalData[jInner] = nTds[j].innerHTML; // jquery.dataTables.js:2220

I have a ajax call, and result string in HTML format. I convert them into HTML nodes, and that part is ok.

var $result = $('<div/>').html(result).find("*:first");
// simlar to $result=$(result) but much more faster in Fx

Then I activate enable the result from a plain table to a sortable datatable. The speed is acceptable in Fx (around 4sec for 900 rows), but unacceptable in IE8 (more then 100 seconds).

I check it deep using the buildin profiler, and found the above single line take all 99.9% of the time, how can I speed it up? anything I missed?

            nTrs = oSettings.nTable.getElementsByTagName('tbody')[0].childNodes;
            for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
            {
                if ( nTrs[i].nodeName == "TR" )
                {
                    iThisIndex = oSettings.aoData.length;
                    oSettings.aoData.push( {
                        "nTr": nTrs[i],
                        "_iId": oSettings.iNextId++,
                        "_aData": [],
                        "_anHidden": [],
                        "_sRowStripe": ''
                    } );

                    oSettings.aiDisplayMaster.push( iThisIndex );

                    aLocalData = oSettings.aoData[iThisIndex]._aData;
                    nTds = nTrs[i].childNodes;
                    jInner = 0;

                    for ( j=0, jLen=nTds.length ; j<jLen ; j++ )
                    {
                        if ( nTds[j].nodeName == "TD" )
                        {
                            aLocalData[jInner] = nTds[j].innerHTML; // jquery.dataTables.js:2220

                            jInner++;
                        }
                    }
                }
            }
Giraud answered 9/3, 2010 at 2:7 Comment(4)
I don't think browsers are particularly good at doing that stuff with 900 rows. In Firefox the fast javascript saves you, but IE is a lot slower with script.Protectionism
I would you use some kind of paging mechanism, we had the same problem with another grid control in IE , the performance of the javascript engine stinks so we ended up giving the user the ability to page the results (or wait for IE).Teilo
Just curious, what does replacing the line with just var result = nTds[j].innerHTML; yield for performance? (forget that it breaks it for the moment)Bothy
I tried before var temp; (function MARK(nTd){ temp=nTd.innerHTML; })(nTd[i]); aLocalData[jInner]=temp; And the IE9 build-in profiler shows ALL the time consumed by the mark.Giraud
K
4

Try using the YUI DataTable. It is very quick for any large table that I throw it at. You can use it with JQuery without any issues.

For example: http://paulisageek.com/compare/cpu/

Kayleen answered 24/3, 2010 at 3:28 Comment(5)
Great page you have there. I just gave the link to couple of friends. Will come in handy during upgrades.Veraveracious
I have few tables, with various size, looks normal within page. They have no scrollbar, but keep their header visible on scroll. I am using FixedHeader plugin with jquery-datatable. Is there something do the same with yui-datatable? e.g. datatables.net/release-datatables/extras/FixedHeader When the table is within the screen, looks normal. When the table is partialy on the screen, a header remain visible. When the table is outside the screen, no addition header.Giraud
There is something that is close, and a little more "HTML-ish". Just use a ScrollingDataTable instead : developer.yahoo.com/yui/datatable/#scrolling . See it live developer.yahoo.com/yui/examples/datatable/dt_fixedscroll.htmlKayleen
Tarjan, I had look on the example, however, it is not the effect I am looking for.Giraud
Your call. I'd go with something that works now, and then tweak the UI later.Kayleen
G
1

I've apply my own patch but still looking for a real solution, it is still very slow in IE (10+ sec) but acceptable.

I read innerHTML once a row and split my own.

                    // For whom in interest
                    // Tested on IE8, Fx3.5
                    .....
                    aLocalData = oSettings.aoData[iThisIndex]._aData;
                    jInner = 0;
                    if(nTrs[i].getElementsByTagName('table').length == 0){
                        nTds =$.trim(nTrs[i].innerHTML).split(/<\/td>\s*/i);
                        for(j=0, jLen=nTds.length; j<jLen; j++){
                            aLocalData[jInner]=nTds[j].replace(/<td[\w\W]*?>/i,'');
                            jInner++;
                        }
                        continue;
                    }
                    nTds = nTrs[i].childNodes;
                    .....

If anyone know why innerHTML are slow, please let me know.

Giraud answered 9/3, 2010 at 9:9 Comment(0)
L
1

A table with 10 columns and 900 rows will call the innerHTML function for 9000 times. Instead append the innerHTML contents to an array and call innerHTML only once at end of the table.

Something like:

var contentArray = ["","","Cell Content","",""];
container.innerHTML(contentArray.join(""));

This way the innerHTML is called only once in the table build process. If not you could call innerHTML at end of each row bringing down the number of times you call innerHTML to 900.

Lara answered 24/3, 2010 at 4:36 Comment(1)
The code came from jquery-datatable which already support both Html table and AJAX as datasource.Giraud
D
1

Did you ever consider using XML Data Island for this? This is a little bit tricky, but works pretty fast. Here's how you can bind HTML table to XML Data Island:

http://www.devx.com/tips/Tip/14109

(in the island you can load data from remote source, so it's like Ajax).

Dishonest answered 25/3, 2010 at 21:7 Comment(0)
W
1

I would suggest avoiding innerHTML with IE and trying the XML DOM elements. I tried different fixes for loops but the delay is from pulling the values of the HTML element. The issue is IE's javascript engine and requires work arounds to get acceptable performance.

After much trial and error I came up with the following improvement over innerHTML:

   var start = new Date().getTime()
     var resp=[];
     var dataTbl = $(data).find('#tbl').get(0);  // jquery Ajax call to html, .get(0) for real DOM
     var dataObj = dataTbl.rows;  
     for (var i = 1, l = dataObj.length; i < l; i++) { 
     resp[i] = { 
        label: dataObj[i].firstChild.firstChild.nodeValue,
        value: dataObj[i].lastChild.firstChild.nodeValue
      };
    };
  alert("On Array 5(DOM:For:array[index]:i++:): Milliseconds: " + ( new Date().getTime() - start) );

IE8 versus FireFox 3 performance(non-scientific): Scrap a table of 2 column : 1655 rows into object array

  • Array 1(JQuery .each): Milliseconds: 20203 / 68
  • Array 2(for:array.push): Milliseconds: 19531 / 41
  • Array 3(while:array.push): Milliseconds: 19609 / 44
  • Array 4(For:array[index]): Milliseconds: 20562 / 326
  • Array 5(DOM:For:array[index]:i++:): Milliseconds: 797 / 245 ***Winner
  • Array 6(DOM:For:array[index]:i+=): Milliseconds: 828 / 245
  • Array 7(DOM:For:array.push:i++): Milliseconds: 797 / 250
Whiteley answered 13/2, 2012 at 23:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.