Низкая производительность с таблицами в режиме стандартов Internet Explorer 8 - PullRequest
17 голосов
/ 05 января 2011

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

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

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

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

  • Отчеты Dynatraceпоказать, что почти 100% процессорного времени тратится на «Расчет общего макета».Этого не происходит, если вместо таблиц используются <div> s (см. Ниже).
  • Переключение режима документа в стандарты IE7 или режим Quirks через панель инструментов Dev решает проблему.
  • Из-заИз-за ограничений, накладываемых на среду, в которой я работаю, IE8 работает в браузерном режиме IE8 с режимом документа стандартов IE8.Изменение этого параметра с помощью панели инструментов Dev не влияет на производительность.
  • Замена решения <table> на подход <div> / <span> повышает производительность, исключая количество узлов DOM в себе каквиновник.
  • В этом примере события наведения мыши добавляются к каждому <tr>, но использование делегирования событий не уменьшает проблему.Фактически, если я заменю решение для наведения мыши на setInterval, где каждые 50 мс выделяется случайная строка, происходит такое же снижение производительности.
  • Я протестировал и подтвердил это поведение на нескольких разных машинах (все Windows XP, Intel Core Duo @ 2,33 ГГц, с 3,5 ГБ ОЗУ) в моей рабочей среде.Все они демонстрируют одинаковое поведение.
  • Я тестировал HTML 4 Strict, XHTML 1.0 строго и HTML5 doctypes.Все они демонстрируют одинаковое поведение.
  • Предварительный рендеринг таблицы на стороне сервера не влияет на производительность во время выполнения.
  • Использование макета таблицы: фиксированная и / или заданная ширина <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

Ответы [ 6 ]

6 голосов
/ 07 января 2011

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

Кажется, это основная проблема в том, как 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 голосов
/ 19 января 2011

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

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

1 голос
/ 05 января 2011

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

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

1 голос
/ 05 января 2011

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

В вашем случае я вижу одно улучшение, которое можно сделать. Вместо добавления обработчиков событий в каждую строку, используйте всплывающее окно событий и ловите движения мыши на уровне таблицы. Это означает, что вместо 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>

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

0 голосов
/ 01 июля 2013

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

0 голосов
/ 05 января 2011

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

...