javascript - Bajo rendimiento con tablas en el modo de estándares de Internet Explorer 8
performance html-table (6)
Al usar una tabla con una cantidad razonable de datos (100 filas por 50 columnas), observo que el rendimiento de IE8 se degrada de manera inaceptable (solo en el modo de representación de estándares IE8). El uso de la CPU aumenta al 100% y el navegador se vuelve muy lento. Aumentar la cantidad de datos en la tabla amplifica la lentitud.
Esto se hizo evidente al aplicar un color de fondo al pasar el mouse sobre una fila, pero la degradación del rendimiento parece ocurrir con cualquier cambio de estilo, y no está relacionado con el manejo del evento del hover.
Se adjunta un caso de prueba muy simple con el que puedo reproducir constantemente el problema.
Un par de notas sobre el tema:
- Los informes de Dynatrace muestran que casi el 100% del tiempo de CPU se gasta en "Calcular el diseño genérico". Esto no ocurre si se usan
<div>
s en lugar de tablas (ver más abajo). - Al cambiar el Modo de documento a Estándares IE7 o Modo Quirks a través de la barra de herramientas Dev, se soluciona el problema.
- Debido a las restricciones impuestas en el entorno en el que trabajo, IE8 se ejecuta en el modo de navegador de modo compatible de IE8, con el modo de documento de estándares de IE8. Cambiar esta configuración a través de la barra de herramientas Dev no tiene ningún efecto en el rendimiento.
- Reemplazar la solución
<table>
con el enfoque<div>
/<span>
mejora el rendimiento, descartando la cantidad de nodos DOM en sí como el culpable. - El ejemplo agrega eventos mouseover a cada
<tr>
, pero el uso de la delegación de eventos no mitiga el problema. De hecho, si sustituyo la solución mouseover con unsetInterval
donde cadasetInterval
ms se resalta una fila aleatoria, se produce la misma degradación del rendimiento. - He probado y confirmado este comportamiento en varias máquinas diferentes (todas con Windows XP, Intel Core Duo @ 2.33 Ghz, con 3.5 GB de RAM) en mi entorno de trabajo. Todos exhiben el mismo comportamiento.
- He probado HTML 4 Strict, XHTML 1.0 Strict y HTML5 doctypes. Todos exhiben el mismo comportamiento.
- La representación previa de la tabla del lado del servidor no tiene ningún efecto en el rendimiento en tiempo de ejecución.
- Uso de diseño de tabla: los anchos fijos y / o de configuración en los
<td>
no tienen efecto. - Usar estilos CSS a través de clases en lugar de manipular los estilos a través de JavaScript no tiene ningún efecto.
- La aplicación de un color de fondo a las
<td>
en lugar de<tr>
no tiene ningún efecto.
Creo que he agotado mis opciones para mejorar el rendimiento del efecto mouseover desde una perspectiva de codificación, y tengo que llegar a la conclusión de que el manejo de <table>
IE8 es extremadamente deficiente, aunque si siempre es así, me sorprende que no haya encontrado más información sobre este tema.
Espero que alguien más pueda confirmar este comportamiento en un entorno separado de IE8, o señalar un error por mi parte. Tengo curiosidad por saber por qué IE8 en estándares tiene un rendimiento mucho peor que IE6, o IE8 que se ejecuta en modo 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>
El problema no se limita a las tablas. He visto problemas similares con otros elementos en la página. Echa un vistazo a este ejemplo con los botones: bajo rendimiento con los estándares IE8
Los botones Sure 500 son excesivos, pero la misma página se reproduce perfectamente utilizando los estándares de IE7 y en otros navegadores. Quiero saber qué está causando esto y cómo se puede solucionar.
Las tablas son realmente caras con el procesamiento, por lo tanto, la gente dice que nunca debes usarlas a menos que estén destinadas a datos tabulares. Si asigna los anchos de la tabla, normalmente se acelera el tiempo de representación.
En su caso veo una mejora que se puede hacer. En lugar de agregar controladores de eventos a cada fila, use la propagación de eventos y capture los movimientos del mouse en el nivel de la tabla. Esto significa que en lugar de que se agreguen 50 controladores de eventos para el mouseover, agrega uno.
Una forma de hacerlo:
<!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>
Quédate con la delegación de eventos y "diseño de tabla: arreglado"; y luego intente configurar la visibility:hidden
en las filas que no se muestran en la pantalla. Cuando se desplazan a visibility:auto;
ellos.
O mejor aún: separe las filas del DOM cuando no esté a la vista y use una fila de "búfer" para mantener la altura de la barra de desplazamiento y la posición de desplazamiento (recomiendo usar el método detach()
jQuery).
Sé que esto puede ser un tramo largo, pero es posible que desee utilizar la creación de perfiles de firebug en Firefox y dónde está la pérdida de rendimiento.
Por "largo alcance" quiero decir que el mismo problema puede no ser relevante para ambos navegadores. Sugerí un navegador diferente porque sé que el perfil de firebug no está disponible en MSIE afaik, no por las preferencias personales del navegador.
Si bien no se ha encontrado ninguna explicación para el bajo rendimiento, otros usuarios han confirmado el comportamiento (lo que reduce la probabilidad de un problema ambiental).
Parece que es un problema central en la forma en que IE8 trata la manipulación del estilo <table>
, y presentaré un error al equipo de IE. Ya creé una publicación en el foro de Internet Explorer Development Forum que hasta el momento no arrojó resultados: http://social.msdn.microsoft.com/Forums/en-US/iewebdevelopment/thread/2afa46aa-16bb-4e65-be38-a6de19b2b2e9
Sin embargo, hay soluciones alternativas disponibles para lograr un efecto de desplazamiento utilizable en IE8, las dos más dignas de consideración son:
- Reemplace la solución
<table>
con los elementos<div>
y<span>
- Falsifique el efecto de desplazamiento al colocar un elemento
<div>
detrás de la<table>
transparente como lo sugiere David Murdoch. Una prueba de concepto rudimentaria se puede encontrar en http://jsfiddle.net/YarnT/1/
Publicaré cualquier actualización aquí en caso de que sepa algo nuevo, o reciba una respuesta del equipo de IE.
Siendo realistas, con IE, es mejor que construyas todo el HTML y lo introduzcas a la vez con style = "" o las clases que estás buscando. Si puede manejar las regresiones, genere X filas por tabla y varias tablas para ''transmitirlas'' en los cambios.