Contexto:
Tengo una aplicación web que procesa y muestra enorme de archivos de registro. Son por lo general sólo alrededor de 100 mil líneas de largo, pero puede ser de hasta 4 millones de líneas o más. Para ser capaz de desplazarse a través de ese archivo de registro (tanto iniciada por el usuario y a través de JavaScript) y filtro de las líneas con un rendimiento decente puedo crear un elemento de DOM para cada línea tan pronto como llegan los datos (en JSON a través de ajax). He encontrado este mejor rendimiento, a continuación, construir el código HTML en el back-end. Después me guarde los elementos de un conjunto y que sólo se muestran las líneas que son visibles.

Para un máximo de 100 mil líneas esto sólo toma un par de segundos, pero nada más toma un minuto para 500k líneas (no incluido en la descarga). Quería mejorar el rendimiento aún más, así que he intentado utilizar HTML5 Web de los Trabajadores. El problema ahora es que no puedo crear elementos en una Web de Trabajador, ni siquiera fuera de la DOM. Así que terminé haciendo sólo el json de conversión de HTML en la Web de los Trabajadores y enviar el resultado en el hilo principal. Allí se crea y se almacena en una matriz. Por desgracia esto agravó el rendimiento y ahora se hace en menos de 30 segundos más.

Pregunta: Así que es allí cualquier manera, que yo no soy consciente de que, para crear elementos del DOM, fuera el árbol DOM, en una Web Trabajador? Si no, ¿por qué no? A mí me parece que esto no se puede crear problemas de simultaneidad, como la creación de los elementos que podría suceder en paralelo sin problemas.

  • Tiene usted pensó de una solución, por el que se solicita el registro de líneas en la demanda? El análisis de 4M de líneas de registro-archivos a la vez es una tarea pesada e incluso si se puede usar el WebWorker en una forma efectiva de aquí, usted no obtendrá el rendimiento-boost que usted está buscando. Me gustaría recomendar sólo a solicitud de un montón de líneas de proceso y de ellos similares a estos infinita de desplazamiento de páginas.
  • Sí, pero eso es muy difícil de implementar el filtro de opciones. También me gustaría tener que almacenar el formato JSON, como el análisis a JSON en el back-end también toma un minuto y no hay manera de hacer que en las piezas. También disminuiría el desplazamiento y rendimiento de la filtración, que atm tarda unos milisegundos o incluso nanosegundos.

9 Comentarios

  1. 15

    Bien, hice un poco más de investigación con la información de @Bergi siempre y encontró la siguiente discusión sobre la W3C lista de correo:

    http://w3-org.9356.n7.nabble.com/Limited-DOM-in-Web-Workers-td44284.html

    Y el extracto que respuestas ¿por qué no hay acceso a la XML parser o analizador DOM en la Web del Trabajador:

    Estás asumiendo que ninguno de los DOM implementación de código utiliza cualquier tipo
    de los no-objetos DOM, nunca, o que si lo hace con los objetos están totalmente
    de subprocesos. Eso no sólo no es el caso, al menos en Gecko.

    El problema en este caso no es el mismo objeto DOM de ser tocado en
    varios subprocesos. El problema es de dos objetos DOM en diferentes hilos
    ambos tocar algunas global tercer objeto.

    Por ejemplo, el analizador de XML tiene que hacer algunas cosas que en Gecko puede
    sólo se puede hacer en el hilo principal (DTD de carga, de improviso; hay un
    algunos otros de los que he visto antes pero no recuerdo de improviso).

    No obstante, también es una solución que se ha mencionado, que es el uso de una tercera parte de la implementación de los analizadores, de los cuales jsdom es un ejemplo. Con esto usted puede incluso tener acceso a su propio Documento separado.

    • La discusión en la lista de correo es que parece ser mera handwaving. Por supuesto, si el corriente versión de Gecko no puede hacerlo, eso está bien, Pero eso no significa que un futuro versión debería tener esta limitación también.
    • No parece ser suficiente interés en que algún día podría convertirse en una posibilidad: 2ality.com/2012/11/canvas-in-workers.html
    • Es por eso que virtual DOM es tan grande. U puede tener complejo de cheques y de las operaciones de representación en otro de los hilos.
  2. 11

    Así que es allí cualquier manera, que yo no soy consciente de que, para crear elementos del DOM, fuera el árbol DOM, en una Web Trabajador?

    No.

    ¿Por qué no? A mí me parece que esto no se puede crear problemas de simultaneidad, como la creación de los elementos que podría suceder en paralelo sin problemas.

    No para la creación de ellos, que está a la derecha. Pero para su adición a los principales document – tendrían que ser enviados a una memoria diferente (como es posible que blobs), de modo que son inaccesibles desde el trabajador a partir de entonces. Sin embargo, no hay absolutamente ninguna manejo de Documentos disponibles en WebWorkers.

    Puedo crear un elemento de DOM para cada línea tan pronto como llegan los datos (en JSON a través de ajax). Después me guarde los elementos de un conjunto y que sólo se muestran las líneas que son visibles.

    La construcción de más de 500k de elementos del DOM es la tarea pesada. Intenta crear elementos DOM sólo para las líneas que son visibles. Para mejorar el rendimiento y mostrando el primer par de líneas más rápido, usted también puede fragmento de su transformación en unidades más pequeñas y el uso de los tiempos de espera en el medio. Ver Cómo dejar de intensa Javascript bucle de congelación del navegador

    • Uno de los problemas con la creación de los elementos del DOM on-the-fly es que cajeros puedo usar elementos para sostener varios valores de datos, como el índice. Debido a que el índice de cambios cuando las líneas son filtrados, tengo referencias para el elemento en lugares donde el índice es necesario. He utilizado para actualizar en esos lugares también, pero que tomó demasiado tiempo, ya que son un montón de ellos. Si tengo el tiempo suficiente a la izquierda, a continuación, que podría intentar su camino y ver si puedo tienda se refieren a los índices (y otros valores) de otra manera.
    • Cómo sobre usted mantener todas las líneas como Objetos de JavaScript, y sólo conservar la mayor cantidad de objetos DOM como no hay espacio en la pantalla? Al desplazarse, puede cambiar la asignación objeto DOM -> de objetos de JavaScript, en lugar de cambiar que DOM objetos son visibles. Esto te permitirá filtrar y desplazarse muy rápidamente, y evita la creación de demasiados objetos DOM.
    • Sí, eso es lo que mi segunda sugerencia medios. Y es lo de alto rendimiento en la tabla scroller bibliotecas hacer.
  3. 4

    Usted tiene que entender la naturaleza de un webworker. Programación con hilos es duro, especialmente si vas a compartir la memoria; cosas extrañas pueden suceder. JavaScript no está equipado para lidiar con cualquier tipo de hilo-como el intercalado.

    El enfoque de webworkers es que hay no de memoria compartida. Obviamente, esto conduce a la conclusión de que no se puede acceder al DOM.

    • Me doy cuenta de que, para la creación de elementos fuera del árbol DOM no habría necesidad de memoria compartida, no? La única cosa que necesita ser compartida es la lógica para crear los elementos, que, supongo, puede ser copiado, si es necesario.
    • El acceso a la DOM a través de document que es una variable global, así que .. no 🙁
    • Puede acceder a la API del DOM a través de alguna de objetos de documento, no sólo el adjunto a la ventana de objetos. Por lo que no tiene que ser una variable global.
    • Entiendo eso, pero ¿cómo se va a obtener un nuevo documento y cómo se va a transferir los nodos? Dudo importNode va a trabajar en esto. También, haciendo de Nodos DOM no es que caro, acaba de transferir algunos datos de nuevo y hacer el DOM conversión en el guión principal.
    • usted no puede tener acceso a la nativ-dom-api implementado por el navegador de un WebWorker, en este punto, estás en lo correcto. Sin embargo Alohci de un enfoque más teórico que apunta a la costumbre de la js-implementaciones, que es lo que yo entendí de él. Acerca de tranfering los nodos entre los WebWorker y el documento original: Esto sólo puede hacerse a través de los mensajes de sistema y requiere de algún tipo de serialización. HTML es la opción obvia, pero refiriéndose a la OP esta técnica no salen tan bien.
    • Esa es probablemente la forma de pensar, sí. Para que valga la pena, la serialización/deserialización en el postMessage interfaz tendría que especialmente optimizado para nodos DOM. Pero supongo que los navegadores probablemente podría hacer que de una manera bastante eficaz, dado el hecho de que sabemos que el innerHTML es generalmente más rápido que la construcción de un árbol DOM nodo por nodo, y que un optimizado deserialización tendría menos trabajo para hacer que innerHTML.
    • tienes razón innerHTML debe realizar mejor que el más expresivo dom-manipulación-métodos, vea este punto de referencia para una prueba. Sin embargo, yo no creo que el cuello de botella, ya que el OP statet que el desplazamiento no es el problema, pero el análisis de las json en dom parece ser muy lento.
    • Mediante el documento.createElement y innerHTML y la reducción de la recolección de basura la tengo abajo de 20 a 30 segundos para 500k líneas (sin los Web workers).
    • como muchas cosas de la creación de elementos del DOM no es que caro no, pero la creación de cientos de miles de ellos.

  4. 4

    No hay una manera directa para acceder al DOM a través de la Web de los Trabajadores.
    Recientemente he publicado @ciclo/sandbox, es todavía WIP, pero demuestra con el Ciclo de JS arquitectura es bastante recta hacia adelante para declarar la interfaz de usuario de comportamiento en la Web del Trabajador. El real DOM es sólo tocó en el hilo principal, pero los detectores de eventos, y DOM actualizaciones son indirectamente declarado en el trabajador, y una sintetizado objeto de evento es enviado cuando algo sucede en los oyentes. Además es sencillo de montar estas de espacio aislado de los Componentes del Ciclo de side-by-side regular de los Componentes del Ciclo.

    http://github.com/aronallen/-cycle-sandbox/

  5. 2

    No veo ninguna razón por qué usted no se puede construir html cadenas de uso de internet de los trabajadores. Pero tampoco no creo que hubiera mucho de un aumento de rendimiento.

    Esto no está relacionado con la Web de los Trabajadores, sino que se relaciona con el problema que estamos intentando resolver. Aquí hay algunas cosa que podría ayudar a acelerar las cosas:

    1. Uso DocumentFragments. Agregar elementos como los datos llegan, y añadir los fragmentos de la DOM en un intervalo (una vez por segundo). De esta manera usted no tiene que tocar el DOM (e incurrir en un rediseño) cada vez que una línea de texto está cargado.

    2. Hacer carga en segundo plano, y sólo analizar las líneas a medida que el usuario llega a la parte inferior del área de desplazamiento.

    • El primero de los consejos sobre el uso de un tiempo de funciones tendrá el efecto contrario de lo que usted podría esperar. Navegador no vuelva a dibujar o representar después de cada DOM-manipulación, pero siempre que la pila de llamadas se hace vacío y antes de la siguiente tarea asincrónica se obtiene de la cola. Eso significa que usted va a producir mucho más de procesamiento de llamadas que se necesita cuando se puede dividir la tarea en pequeños asincrónica porciones, que se añadirán a la cola. Esto se refiere a los eventos de javascript-loop.
    • La segunda recomendación es comúnmente conocida como la obtención de datos sobre la demanda. Que significa obtener y procesar sólo cuando son necesarios. Y en mi humilde opinión. esta sería la solución más confiable para este problema, sin embargo el OP ya se quejaron acerca de otros temas en función de esta solución en los comentarios debajo de su pregunta.
    • El camino es la adición de elementos al dom, es incurrir en el número máximo de redibuja. DocumentFragments puede ser creado y manipulado fuera de la pantalla. Por saltarse los marcos donde se redibuja podría haber ocurrido, él salva a algunos de ciclos de procesador. No estoy sugiriendo que él la carga de los datos en la demanda. Soy lo que sugiere que la carga de los datos en segundo plano, y sólo analizarlo en dom elementos como sean necesarios. Como para el filtrado, me gustaría recomendar la aplicación de las clases a los elementos, y la configuración de su pantalla de acuerdo a las reglas del filtro de
    • Ah bueno, me puse un poco confundido por los términos «nuevo trazado de la» y «Representación». Permite obtener algunas aclaraciones en aquí: «Rediseñar» se refiere a un proceso en el que el Navegador es en realidad la actualización de la pantalla, mientras que la «Representación» que puede suceder en el fondo. Por ejemplo, si usted hizo un cambio en el tamaño de un elemento, que actualmente está conectado al documento y visible y, a continuación, acceder a la «offsetWidth» de la propiedad, el Navegador debe realizar «la Representación», para determinar el nuevo calculada de la propiedad, sin embargo el cambio no directamente visible en la pantalla.
    • Documento de fragmentos evitar este problema, porque la offsetHeight propiedad de un elemento dentro de un fragmento de siempre por defecto a cero. Así que tienes razón usted puede salvar la «Representación»-llamadas. Pero de nuevo, no creo que este es el cuello de botella de su algoritmo, dado que hay muy pocas propiedades que requiere de una «Representación»-llamada, y son todos de diseño-que se trate y no debe aparecer durante transpiling de json a html, de todos modos.
    • La creación de elementos DOM no incurrir vuelve a dibujar o representar de nuevo, no hasta que se haya agregado a la real en el árbol DOM. El uso de DocumentFragments o anexando los elementos a otro separado elemented es básicamente el mismo.
    • De vuelta a la sobre-demanda-debate. Veo la diferencia, por lo que son, básicamente, hablando acerca de la captura de los datos durante la inicialización, pero dejar el tratamiento (~= transpiling) cuando están en realidad es necesario. Parece bueno para mí y debería evitar los problemas de la OP se mencionó anteriormente. Creo que el caché de los ya procesados líneas se podría hacer una ligera mejora a esta solución. Lo siento por la respuesta larga.
    • Por cierto, cito a mí mismo aquí «Después puedo guardar los elementos de un conjunto y que sólo se muestran las líneas que son visibles.», por lo que me refería es que cuando el usuario se desplaza me agregue las líneas correspondientes, ya analizados como elementos al DOM, que es básicamente lo que estás sugiriendo.
    • Ahora con lo de la demanda, he pensado mucho en eso cuando estaba aplicación y experimentado varias cosas. Por ejemplo el filtrado como usted sugiere es lento, el selector de jquery para las clases es muy lento y necesidades de todos los elementos para estar en el árbol DOM. La única manera que he encontrado para hacer que sea muy rápido y todavía tiene todos los elementos del árbol DOM, excepto los que son visibles, es mantener una serie de índices de las líneas que no se filtran. El ser capaz de actualizar este rápido también he creado matrices con los índices para cada tipo, por lo que fácilmente se pueden restar o añadir a ellos.
    • Lo que este filtrado problema de los medios es el que necesito para procesar todos los registros de una sola vez de hacerlo de la manera que acabo de explicar. También hay otras cuestiones para las cuales necesito más información de la que un par de líneas. En la final se iba a hacer la experiencia más lento después de la transformación, que no es lo que quiero. El usuario está preparado para esperar algún tiempo durante el procesamiento, pero que lo quiere trabajar rápido después de eso, sólo estoy tratando de minimizar el tiempo de procesamiento.

  6. 1

    Usted tiene un par de anti-patrones de diseño:

    1. La creación de un objeto DOM tiene una considerable sobrecarga, y que son
      creando potencialmente millones de ellos a la vez.
    2. Tratando de conseguir una web trabajador para manejar el DOM es exactamente lo que la web
      los trabajadores son no para. Ellos hacen todo lo demás, así que el DOM bucle de eventos permanece sensible.

    Puede utilizar un cursor patrón para desplazarse a través de arbitrariamente grande conjuntos de datos.

    1. DOM envía un mensaje a los trabajadores con la posición de inicio y el número de líneas de pedido (cursor).
    2. Web trabajador accesos aleatorios registros, vuelve la tomó de las líneas (cursor de datos).
    3. DOM actualizaciones de un elemento con el async cursor evento de respuesta.

    De esta manera, el trabajo pesado se hace por el trabajador, en cuyo caso el bucle se bloquea durante la captura en lugar de la DOM, lo que resulta en feliz no-usuarios bloqueados maravillándose de cómo suavizar todas sus animaciones están.

  7. 0

    Así que no se pueden crear directamente DOM en un webworker – sin embargo, no puede ser otra opción para hacer un poco justo de su procesamiento fuera del hilo principal.

    Echa un vistazo a este jsPerf acabo de crear: http://jsperf.com/dom-construction-obj-vs-str

    Esencialmente, usted podría ser emisores de POJSO que tienen todos los mismos valores que usted recibe de un DOM, y convertir a objetos DOM después de recibir el mensaje (esto es lo que están haciendo cuando usted consigue HTML de vuelta, después de todo; POJSOs son sólo los gastos son menores, en virtud de que no requiere más de la cadena de procesamiento). De esta manera usted podría incluso hacer cosas como emitir los detectores de eventos y tal (por ejemplo, anteponiendo el nombre del evento, con ‘!’, y tener el valor de mapa para algunos plantilla suministrada argumento vista).

    Mientras tanto, sin el analizador DOM disponible, usted tendrá su propia cosa para convertir una plantilla como sea necesario, o para compilar uno a un formato rápido.

    • ¿Estás seguro de que factory.removeChild(ret); no afecta a su prueba?
    • No parece. JSPerf es un poco rompió en estos días, así que no podía editar el antiguo: jsperf.com/dom-construction-3
    • Por cierto, incluso añadiendo el paso de analizar el JSON a partir de una cadena de no hacer que el Objeto->DOM caso peor que el estándar HTML de análisis de caso. jsperf.com/dom-construction-4.
  8. 0

    No se puede crear elementos DOM en una web de trabajo, pero usted puede crear una función que acepta el mensaje de que la web trabajador, que does crear los elementos del DOM. Creo que el se digne que tu buscas se llama matriz de sujeción. Y que se necesita para la mezcla con la web trabajador patrón de diseño.

Dejar respuesta

Please enter your comment!
Please enter your name here