javascript - img - title html attribute
¿El uso de un fragmento de documento realmente mejora el rendimiento? (7)
El jsperf de wolfram77 contiene un bucle for adicional en el ejemplo de no fragmento que es la causa principal de la diferencia de rendimiento, no el DocumentFragment. Al eliminar este bucle adicional para for, puede lograr el mismo resultado pero el rendimiento es completamente diferente:
Así que todavía no veo un beneficio de rendimiento en la parte de secuencias de comandos, pero puede haber uno en el navegador cuando tenga que volver a pintar para cada elemento adjunto.
Tengo una duda sobre el rendimiento en JS.
Diga, tengo el siguiente código:
var divContainer = document.createElement("div"); divContainer.id="container";
var divHeader = document.createElement("div"); divHeader.id="header";
var divData = document.createElement("div"); divData.id="data";
var divFooter = document.createElement("div"); divFooter.id="footer";
divContainer.appendChild( divHeader );
divContainer.appendChild( divData );
divContainer.appendChild( divFooter );
document.getElementById("someElement").appendChild( divContainer );
Este código simplemente crea el shell para algunas otras funciones para crear una grilla, el proceso para crear la grilla es muy complejo y con muchas validaciones y actualmente estoy usando 2 métodos para llenar la grilla, uno creando todo el html en una variable de matriz y el otro creando elementos y agregándolos a un documentFragment
.
Mi pregunta es si realmente hay una mejora en el rendimiento al usar fragmentos, tal como los entiendo: administran los elementos en la memoria, por lo que no se adjuntan al documento, por lo que no activan el recálculo de DOM y otras cosas desagradables. Pero por la forma en que estoy creando mis variables, no están asociadas a ningún elemento DOM hasta que añada el contenedor a la página real.
Así que me preguntaba si el código anterior tiene mejor rendimiento que usar un fragmento de documento que lo envuelve todo así:
var fragment = document.createDocumentFragment();
var divContainer = document.createElement("div"); divContainer.id="container";
var divHeader = document.createElement("div"); divHeader.id="header";
var divData = document.createElement("div"); divData.id="data";
var divFooter = document.createElement("div"); divFooter.id="footer";
divContainer.appendChild( divHeader );
divContainer.appendChild( divData );
divContainer.appendChild( divFooter );
fragment.appendChild( divContainer )
document.getElementById("someElement").appendChild( fragment.cloneNode(true) );
Como ya he dicho, esta es una pregunta relacionada con el rendimiento, sé que como práctica recomendada se recomienda usar fragmentos, pero no puedo dejar de pensar que al hacerlo solo se crea un nuevo objeto en la memoria y no hace nada, así que supongo que abandonar el fragmento en este caso es válido.
Esperemos que algún js guru / dios brille una luz de esperanza aquí y nos ayude con este problema.
Edit : Entonces, he estado buscando cosas relacionadas con este problema y parece que documentFragments no necesariamente significa un mejor rendimiento.
Es solo un contenedor de nodos "en memoria". La diferencia entre un fragmento y digamos, un <div>
es que el fragmento no tiene padre y nunca estará en el DOM, solo en la memoria, lo que significa que las operaciones hechas en el fragmento son más rápidas ya que no hay manipulación del DOM .
La documentación de W3C en documentFragments es muy vaga pero hasta el punto y, además, el navegador favorito de todos no usa fragmentos reales, en su lugar, crea un nuevo documento de acuerdo con esta documentación de MSDN . Lo que significa que los fragmentos en IE son más lentos.
Entonces, la pregunta prevalece, si creo un elemento (un <div>
por ejemplo) en una variable pero NO LO AÑADIMO AL DOM, agrego elementos (divs, tablas, etc.) y esas cosas y después de todo el trabajo se ha hecho (bucles, validaciones, diseño de elementos), ese elemento se agrega, ¿es lo mismo que un fragmento?
Dado que IE usa un fragmento "falso", diría que al menos en IE usando ese enfoque (usar un elemento como un div, no un fragmento) es mejor, realmente no me importa el IE pero necesito probarlo (política de la oficina).
Además, si creo todo el html en una matriz de esta manera:
var arrHTML = ["<table>","<tr>", ....];
y luego haz esto
document.getElementById("someElement").innerHTML = arrHTML.join("");
Es mucho más rápido en IE, pero otros navegadores principales (FF, Chrome, Safari y Opera) funcionan mejor cuando usan un contenedor y luego lo agregan (fragmento o div).
Todo esto se debe a que el proceso para crear todos los elementos se hace realmente rápido, entre 8 y 10 segundos para crear hasta 20,000 filas con 24 columnas, hay muchos elementos / etiquetas, pero el navegador parece congelarse unos segundos cuando todos están agregados a la vez, si los intento agregarlos uno por uno, es un infierno.
Gracias de nuevo amigos, esto es realmente interesante y divertido.
En mi experiencia, las operaciones de dominar suelen ocurrir solo después de que la pila de llamadas esté vacía. Si pongo muchas operaciones dom en el bucle, el navegador se congela durante un tiempo y luego muestra todo a la vez. Puede romper la pila usando setTimeout para mostrar el resultado más frecuentemente si lo desea. Por esta razón, creo que ambos métodos deberían funcionar de manera similar. Esto es realmente muy extraño a veces, porque si en una pila cambias algún elemento nunca verás su estado antes del cambio (tenía este problema con el objeto de notificación de progreso que innerHTML nunca fue actualizado durante el ciclo, solo comienza el estado y luego final).
He escrito un jspref para probar esto y parece que el fragmento del nodo es 2.34% más rápido
Normalmente, querrá utilizar un fragmento para evitar reflujos (volver a pintar la página). Un buen caso sería si estuvieras haciendo un bucle sobre algo y agregando dentro del bucle, sin embargo, creo que los navegadores modernos ya están optimizados para esto.
Configuré un jsPerf para ilustrar un buen ejemplo de cuándo usar un fragmento here . Notarás en Chrome que apenas hay una diferencia (la optimización moderna funciona, supongo), sin embargo, en IE7 obtengo .08 ops / s sin el fragmento, 3.28 ops / sec con un fragmento.
Por lo tanto, si realiza un bucle en un conjunto de datos de gran tamaño y agrega MUCHOS elementos, en su lugar, use un fragmento, de modo que solo tendrá un reflujo. Si solo agregas dom algunas veces o si solo estás apuntando a navegadores modernos, no es necesario.
Tenía exactamente la misma pregunta que el OP, y después de leer todas las respuestas y los comentarios, parecía que nadie entendía realmente lo que el OP estaba preguntando.
Seguí el ejemplo de la prueba que Nicola Peluchetti publicó y lo modifiqué un poco.
En lugar de agregar elementos a un <div>
y luego agregarlos a documentFragment
, la prueba de fragmentos obtiene los elementos directamente agregados a él (el documentFragment
) en lugar de primero al <div>
. Además, para evitar costos indirectos ocultos, ambas pruebas comienzan creando el contenedor <div>
y el documentFragment
, mientras que cada prueba solo utiliza una u otra.
Tomé la pregunta original para que, básicamente, ¿es más rápido hacer un solo apéndice de nodos usando un <div>
o un documentFragment
como el contenedor?
Parece que usar un <div>
es más rápido, al menos en Chrome 49.
http://jsperf.com/document-fragment-test-peluchetti/39
El único caso de uso que se me ocurre para documentFragment
(en este momento) es si requiere menos memoria (lo que podría ser insignificante), o si tiene un montón de nodos hermanos para anexar que no desea incluir en un " contenedor "elemento. documentFragment
es como un contenedor que se disuelve dejando solo su contenido.
Fragmento de documento es mucho más rápido cuando se utiliza para insertar un conjunto de elementos en varios lugares . La mayoría de las respuestas aquí señalan su falta de utilidad, pero esto es para demostrar su fortaleza.
Tomemos un ejemplo.
Digamos que necesitamos agregar 20 divs en 10 elementos con un contenedor de clase.
Sin:
var elements = [];
for(var i=20; i--;) elements.push(document.createElement("div"));
var e = document.getElementsByClassName("container");
for(var i=e.length; i--;) {
for(var j=20; j--;) e[i].appendChild(elements[j].cloneNode(true));
}
Con:
var frag = document.createDocumentFragment();
for(var i=20; i--;) frag.appendChild(document.createElement("div"));
var e = document.getElementsByClassName("container");
for(var i=e.length; i--;) e[i].appendChild(frag.cloneNode(true));
Para mí, usar un fragmento de documento resulta ser 16 veces más rápido en Chrome 48.
<!DOCTYPE html>
<html>
<head>
<title>TODO supply a title</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div ms-controller=''for1''>
<ul>
</ul>
</div>
<script>
var ul = document.querySelector(''ul'');
console.time(''no fragment'');
for(var i=0;i<1000000;i++){
var li = document.createElement(''li'');
li.innerText = i;
ul.appendChild(li);
}
console.timeEnd(''no fragment'');
console.time(''has fragment'');;
var frg = document.createDocumentFragment()
for(var i=0;i<1000000;i++){
var li = document.createElement(''li'');
li.innerText = i+''fragment'';
frg.appendChild(li);
}
ul.appendChild(frg)
console.timeEnd(''has fragment'');
</script>
</body>
</html>
el resultado es ningún fragmento: 1615.278ms testFragment.html: 36 tiene fragmento: 2908.286ms
así, ningún Fragmento es más rápido. Creo que la razón es que el cromo hizo algo.