Плохая производительность с таблицами в стандарте 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
Ответы
Ответ 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 строк в таблице и несколько таблиц на" поток" в изменениях.