Как ускорить чтение innerHTML в IE8? - PullRequest
7 голосов
/ 09 марта 2010

Я использую JQuery с плагином DataTable, и теперь у меня большая проблема с производительностью в следующей строке.

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

У меня есть вызов ajax и строка результата в формате HTML. Я конвертирую их в узлы HTML, и с этой частью все в порядке.

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

Затем я активирую включение результата из простой таблицы в сортируемую таблицу данных. Скорость приемлема в Fx (около 4 секунд для 900 строк), но недопустима в IE8 (более 100 секунд).

Я глубоко проверил его с помощью встроенного профилировщика и обнаружил, что приведенная выше строка занимает все 99,9% времени, как я могу ускорить его? что я пропустил?

            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++;
                        }
                    }
                }
            }

Ответы [ 5 ]

4 голосов
/ 24 марта 2010

Попробуйте использовать YUI DataTable . Это очень быстро для любого большого стола, в который я кидаю его. Вы можете использовать его с JQuery без каких-либо проблем.

Например: http://paulisageek.com/compare/cpu/

1 голос
/ 14 февраля 2012

Я бы рекомендовал избегать innerHTML с IE и пробовать элементы XML DOM. Я пробовал разные исправления для циклов, но задержка заключается в получении значений элемента HTML. Проблема заключается в движке javascript IE, который требует обходных путей для достижения приемлемой производительности.

После долгих проб и ошибок я обнаружил следующее улучшение по сравнению с 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 и FireFox 3 (ненаучно): очистка таблицы из 2 столбцов: 1655 строк в массив объектов

  • Массив 1 (JQuery .each): миллисекунды: 20203/68
  • Массив 2 (для: array.push): миллисекунды: 19531/41
  • Массив 3 (while: array.push): миллисекунды: 19609/44
  • Массив 4 (для: массив [индекс]): миллисекунды: 20562/326
  • Массив 5 (ДОМ: Для: массив [индекс]: i ++ :): Миллисекунды: 797/245 *** Победитель
  • Массив 6 (ДОМ: Для: массив [индекс]: i + =): Миллисекунды: 828/245
  • Массив 7 (ДОМ: Для: array.push: i ++): Миллисекунды: 797/250
1 голос
/ 26 марта 2010

Вы когда-нибудь задумывались об использовании XML Data Island для этого? Это немного сложно, но работает довольно быстро. Вот как можно связать таблицу HTML с островом данных XML:

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

(на острове вы можете загружать данные из удаленного источника, так что это как Ajax).

1 голос
/ 24 марта 2010

Таблица с 10 столбцами и 900 строками будет вызывать функцию innerHTML 9000 раз. Вместо этого добавьте содержимое innerHTML в массив и вызовите innerHTML только один раз в конце таблицы.

Что-то вроде:

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

Таким образом, innerHTML вызывается только один раз в процессе построения таблицы. Если нет, вы можете вызвать innerHTML в конце каждой строки, уменьшив количество раз, когда вы вызываете innerHTML до 900.

1 голос
/ 09 марта 2010

Я применил свой собственный патч, но все еще ищу реальное решение, он все еще очень медленный в IE (10+ секунд), но приемлемый.

Я читаю innerHTML один раз подряд и разбиваю свою собственную.

                    // 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;
                    .....

Если кто-нибудь знает, почему innerHTML работает медленно, пожалуйста, дайте мне знать.

...