workers threads support examples end javascript multithreading google-chrome firefox web-worker

javascript - threads - web workers jquery



Trabajador web consume gran cantidad de memoria (1)

Estoy tratando de mejorar el rendimiento en mi aplicación que compara el contenido de dos grandes lienzos.

El problema es que durante la comparación, el hilo principal del navegador está bloqueado, lo que resulta en una IU que no responde. El tiempo de ejecución de la función de comparación toma aproximadamente 10 ms y la comparación se realiza cada 250 ms o 500 ms.

Para resolver ese problema, se me ocurrió la idea de usar otro hilo creando un web worker . Funciona bastante bien en este momento, pero me di cuenta de que consume una cantidad insana de memoria (hasta 600 MB en FF y Chrome; en Edge es de hasta 70 MB, nunca alcanzó los 100 MB en la versión de una sola secuencia en todos los navegadores).

Pensé que dejé algunas referencias y el recolector de basura no puede liberar memoria. Sin embargo, después de un tiempo (todo el día de delete mi aplicación de las partes y tratar de delete , variables / datos null o undefined ), creé el violín a continuación en el que envío un ArrayBuffer 1 ArrayBuffer (aunque lo pasé por transferencia) pero sin Cualquier procesamiento y como puede ver, también consume una gran cantidad de memoria.

¿Alguna idea de cómo puedo resolver ese problema (cualquier solución alternativa o cualquier posible mejora de los trabajadores) y dónde está el problema?

var sortFilterDataWorker = function () { onmessage = function image2compare(ev) { postMessage(''hi''); }; }.toString(); /* PREPARE WORKER AS STRING TO CREATE JS BLOB FILE */ sortFilterDataWorker = sortFilterDataWorker.slice(sortFilterDataWorker.indexOf(''{'') + 1, -1).trim(); var blob = new Blob([sortFilterDataWorker]) // create blob file with worker code , blobUrl = window.URL.createObjectURL(blob) // create pseudo url to blob file , compareWorker = new Worker(blobUrl) ; setInterval(function(){ var oneMB = new ArrayBuffer(8388608); compareWorker.postMessage(oneMB, [oneMB]); // transpile ArrayBuffer }, 250);

FIDDLE

EDITAR:

Descubrí que si finalizo Worker cada n repeticiones y creo una nueva, se libera la memoria más rápido. Pero todavía no es una solución, solo una curiosidad.


Descubrí que si ejecuto el recolector de basura manualmente desde las herramientas del desarrollador -> Línea de tiempo, se borra toda la memoria. De forma similar, si comienzo a interactuar con el contexto de Worker desde la consola, las funciones de llamada parecen desencadenar aleatoriamente gc.

Basado en esto, diría que no hay una referencia pendiente, pero que recibir objetos a través de una transferencia puede no forzar una verificación de gc como lo harían las nuevas solicitudes de asignación.

Volver a transferir el objeto con una respuesta parece solucionar el problema:

postMessage(''hi'', [ev.data]); // process usage stays around 50MB

Como alternativa, asegurarse de que el Trabajador no sea trivial y que necesite realizar asignaciones normales también parece activar adecuadamente gc, es decir:

postMessage(''hi''); var twoMB = new ArrayBuffer(8388608); // usage cycles 70MB - ~220MB