Подтвердить что ты не робот

Плохая производительность с таблицами в стандарте Internet Explorer 8

При использовании таблицы с разумным объемом данных - 100 строк на 50 столбцов - я замечаю, что производительность IE8 неприемлемо снижается (только в режиме рендеринга стандартов IE8). Использование ЦП достигает 100%, и браузер становится очень вялым. Увеличение количества данных в таблице усиливает медлительность.

Это стало очевидным при применении цвета фона при наведении на строку, но ухудшение производительности, похоже, происходит при любом изменении стиля и не связано с обработкой события наведения.

Прикрепленный пример - это очень простой тестовый сценарий, с помощью которого я могу последовательно воспроизводить проблему.

Несколько примечаний по этой проблеме:

  • Отчеты Dynatrace показывают, что почти 100% времени процессора расходуется на "Расчет общей компоновки". Этого не происходит, если вместо таблиц используются <div> (см. Ниже).
  • Переключение режима документа на стандарты IE7 или режим Quirks через панель инструментов Dev устраняет проблему.
  • Из-за ограничений, налагаемых на среду, в которой я работаю, IE8 работает в режиме браузера режима совместимости IE8 с режимом документа стандарта IE8. Изменение этого параметра с помощью панели инструментов Dev не влияет на производительность.
  • Замена решения <table> с помощью подхода <div>/<span> повышает производительность, исключая количество узлов DOM в себе как виновника.
  • Пример добавляет события mouseover к каждому <tr>, но использование делегирования событий не уменьшает проблему. Фактически, если я заменю решение мыши с помощью setInterval, где каждые 50 мс выделяется случайная строка, происходит такое же ухудшение производительности.
  • Я тестировал и подтвердил это поведение на нескольких разных машинах (все Windows XP, Intel Core Duo @2.33 Ghz, с 3.5 ГБ оперативной памяти) в моей рабочей среде. Все проявляют одинаковое поведение.
  • Я протестировал HTML 4 Strict, XHTML 1.0 строгие и доктрины HTML5. Все проявляют одинаковое поведение.
  • Предварительная рендеринг серверной части таблицы не влияет на производительность во время выполнения.
  • Использование табличного макета: фиксированная и/или настройка ширины на <td> не имеет эффекта.
  • Использование стилей CSS через классы вместо управления стилями через JavaScript не имеет эффекта.
  • Применение цвета фона к <td> вместо <tr> не имеет эффекта.

Я полагаю, что исчерпал свои возможности для улучшения производительности эффекта мыши, с точки зрения кодирования, и должен сделать вывод, что обработка IE8 <table> крайне бедна, хотя, если это всегда так плохо, я удивлен, что не нашел более подробная информация по этому вопросу.

Я надеюсь, что кто-то еще сможет подтвердить это поведение в отдельной среде IE8 или указать на ошибку с моей стороны. Мне любопытно узнать, почему IE8 в стандартах работает намного хуже, чем IE6, или IE8 работает в режиме IE7/Quirks.


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
     <meta http-equiv="X-UA-Compatible" content="IE=8">
        <title>IE8 Table Hover</title>
    </head>
    <body>
        <script type="text/javascript">
   var numRows = 100;
   var numCols = 50;

   function renderTable () {
    var a = [];

    a.push('<table id="table"><tbody>');

    for (var i=0; i < numRows; i++) {
     a.push('<tr>');

     for (var j=0; j < numCols; j++) {
      a.push('<td>');
      a.push(i + ':' + j);
      a.push('</td>');  
     }

     a.push('</tr>');
    }

    a.push('</tbody></table>');

    var div = document.createElement('div');
    div.innerHTML = a.join('');
    div = document.body.appendChild(div);

    var rows = div.getElementsByTagName('tr');

    for (var i=0; i < rows.length; i++) {
     rows[i].onmouseover = function (event) {
      this.style.backgroundColor = '#cc0000';
     }

     rows[i].onmouseout = function (event) {
      this.style.backgroundColor = '';
     }
    }
   }

   renderTable();
  </script>
 </body>
</html>

Test Case @jsfiddle

4b9b3361

Ответ 1

Хотя никаких объяснений низкой производительности не найдено, поведение было подтверждено другими пользователями (что уменьшает вероятность возникновения проблем с окружающей средой).

Похоже, что это ключевая проблема в том, как IE8 имеет дело с манерой стиля <table>, и я напишу ошибку с командой IE. Я уже создал сообщение на форуме в форуме по развитию Internet Explorer, который пока не дал никаких результатов: http://social.msdn.microsoft.com/Forums/en-US/iewebdevelopment/thread/2afa46aa-16bb-4e65-be38-a6de19b2b2e9

Однако для достижения полезного эффекта зависания в IE8 существуют обходные пути, наиболее важными из которых являются:

  • Замените решение <table> элементами <div> и <span>
  • Подделка эффекта наведения путем позиционирования элемента <div> за прозрачным <table>, как предложил Дэвид Мердок. Рудиментарное доказательство концепции можно найти на http://jsfiddle.net/YarnT/1/

Я буду публиковать любые обновления здесь, если я узнаю что-нибудь новое или получаю ответ от команды IE.

Ответ 2

Проблема не ограничивается таблицами. Я видел похожие проблемы с другими элементами на странице. Проверьте этот пример с помощью кнопок: Плохая производительность с использованием стандартов IE8

Конечно, 500 кнопок чрезмерны, но одна и та же страница отлично отображает стандарты IE7 и другие браузеры. Я хочу знать, что вызывает это и как оно может быть исправлено.

Ответ 3

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

В вашем случае я вижу одно улучшение, которое можно сделать. Вместо добавления обработчиков событий в каждую строку используйте пузырьки событий и поймайте движения мыши на уровне таблицы. Это означает, что вместо 50 обработчиков событий, добавляемых для мыши, вы добавляете один.

Один из способов сделать это:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
  <head>
   <meta http-equiv="X-UA-Compatible" content="IE=8">
      <title>IE8 Table Hover</title>
   <style type="text/css">
      table, tr, td{ border-collapse: collapse; border: 1px solid black; }        
      tr.high td{ background-color: #FF0; }
    </style>
  </head>
  <body>
    <div id="out">~</div>
    <script type="text/javascript">

var numRows = 100;
var numCols = 50;
function renderTable() {
    var a = [];
    a.push('<table id="myTable"><tbody>');
    for (var i = 0; i < numRows; i++) {
        a.push('<tr>');
        for (var j = 0; j < numCols; j++) {
            a.push('<td>');
            a.push(i + ':' + j);
            a.push('</td>');
        }
        a.push('</tr>');
    }
    a.push('</tbody></table>');
    var div = document.createElement('div');
    div.innerHTML = a.join('');
    div = document.body.appendChild(div);
    var lastHiglight = null;
    var bigTable = document.getElementById("myTable");
    bigTable.onmouseover = function (e) {
        e = e || window.event;
        var elm = e.target || e.srcElement;
        var tag = elm.nodeName.toLowerCase();
        if (tag == "td") {
            if (lastHiglight) {
                lastHiglight.className = "";
            }
            lastHiglight = elm.parentNode;
            lastHiglight.className = "high";
        }
    }
    var reTags = /(td|tr|tbody)/i;
    document.body.onmouseout = bigTable.onmouseout = function (e) {
        e = e || window.event;
        var elm = e.target || e.srcElement;
        var tag = elm.nodeName.toLowerCase();
        if (!reTags.test(tag)) {
            if (lastHiglight) {
                lastHiglight.className = "";
            }
        }
    }
}

renderTable();
    </script>
    <p>Awesome Table</p>
 </body>
</html>

Пример выполнения

Ответ 4

Придерживайтесь делегирования событий и "table-layout: fixed;" а затем попробуйте установить visibility:hidden в строки, которые не отображаются на экране. Когда они прокручиваются в виде visibility:auto; их.

Или еще лучше: отсоедините строки из DOM, когда они не отображаются, и используйте строку "buffer", чтобы поддерживать высоту полосы прокрутки и положение прокрутки (я рекомендую использовать jQuery detach()).

Ответ 5

Я знаю, что это может быть длинным, но вы можете использовать профилирование firebug на firefox и где потеря производительности.

В терминах "long stretch" ​​я имею в виду, что одна и та же проблема может не иметь отношения к обоим браузерам. Я предложил другой браузер, потому что знаю, что профилирование firebug недоступно в MSIE afaik, а не из-за каких-либо личных предпочтений браузера.

Ответ 6

Реально, с IE, вам лучше построить весь HTML и сразу же перевернуть его с помощью стиля = "или классов, которые вы ищете. Если вы можете обрабатывать регрессии, визуализируйте X строк в таблице и несколько таблиц на" поток" в изменениях.