tardan dinero devolver declaracion cuanto javascript

javascript - cuanto tardan en devolver el dinero de la declaracion 2017



Número de Límite de Trabajadores Web (4)

PROBLEMA

Descubrí que existe un límite en la cantidad de trabajadores web que un navegador puede generar.

Ejemplo

HTML / JavaScript principal

<script type="text/javascript"> $(document).ready(function(){ var workers = new Array(); var worker_index = 0; for (var i=0; i < 25; i++) { workers[worker_index] = new Worker(''test.worker.js''); workers[worker_index].onmessage = function(event) { $("#debug").append(''worker.onmessage i = '' + event.data + "<br>"); }; workers[worker_index].postMessage(i); // start the worker. worker_index++; } }); </head> <body> <div id="debug"> </div>

test.worker.js

self.onmessage = function(event) { var i = event.data; self.postMessage(i); };

Esto generará solo 20 líneas de salida en el contenedor cuando use Firefox (versión 14.0.1, Windows 7).

PREGUNTA

¿Hay alguna forma de evitar esto? Las únicas dos ideas que puedo pensar son:

1) Daisy encadenando a los trabajadores de la web, es decir, haciendo que cada trabajador web engendre el siguiente

Ejemplo:

<script type="text/javascript"> $(document).ready(function(){ createWorker(0); }); function createWorker(i) { var worker = new Worker(''test.worker.js''); worker.onmessage = function(event) { var index = event.data; $("#debug").append(''worker.onmessage i = '' + index + "<br>"); if ( index < 25) { index++; createWorker(index); } }; worker.postMessage(i); // start the worker. } </script> </head> <body> <div id="debug"></div>

2) Limite el número de trabajadores web a un número finito y modifique mi código para trabajar con ese límite (es decir, comparta la carga de trabajo entre un número finito de trabajadores web) - algo como esto: http://www.smartjava.org/content/html5-easily-parallelize-jobs-using-web-workers-and-threadpool

Desafortunadamente, el número 1 no parece funcionar (solo un número limitado de trabajadores web se generará en una carga de página). ¿Hay alguna otra solución que deba considerar?


¡Vieja pregunta, revivámosla! prepara epinefrina

He estado buscando utilizar Web Workers para aislar plugins de terceros ya que los trabajadores de la web no pueden acceder a la página de host. Te ayudaré con tus métodos que estoy seguro que ya has resuelto, pero esto es para internet. Luego, daré información relevante de mi investigación.

Descargo de responsabilidad : en los ejemplos en los que utilicé su código, modifiqué y limpié el código para proporcionar un código fuente completo sin jQuery para que usted y otros puedan ejecutarlo fácilmente. También he agregado un temporizador que alerta el tiempo en ms para ejecutar el código.

En todos los ejemplos, hacemos referencia al siguiente archivo genericWorker.js .

genericWorker.js

self.onmessage = function(event) { self.postMessage(event.data); };

Método 1 (Ejecución lineal)

Tu primer método casi funciona. La razón por la que todavía falla es que no está eliminando ningún trabajador una vez que termina con ellos. Esto significa que ocurrirá el mismo resultado (colisión), solo que más lento. Todo lo que necesita para solucionarlo es agregar worker.terminate(); antes de crear un nuevo trabajador para eliminar el anterior de la memoria. Tenga en cuenta que esto hará que la aplicación se ejecute mucho más lentamente, ya que cada trabajador debe crearse, ejecutarse y destruirse antes de que se ejecute el siguiente.

Linear.html

<!DOCTYPE html> <html> <head> <title>Linear</title> </head> <body> <pre id="debug"></pre> <script type="text/javascript"> var debug = document.getElementById(''debug''); var totalWorkers = 250; var index = 0; var start = (new Date).getTime(); function createWorker() { var worker = new Worker(''genericWorker.js''); worker.onmessage = function(event) { debug.appendChild(document.createTextNode(''worker.onmessage i = '' + event.data + ''/n'')); worker.terminate(); if (index < totalWorkers) createWorker(index); else alert((new Date).getTime() - start); }; worker.postMessage(index++); // start the worker. } createWorker(); </script> </body> <html>

Método 2 (grupo de subprocesos)

El uso de un grupo de subprocesos debe aumentar considerablemente la velocidad de ejecución. En lugar de utilizar una biblioteca con una jerga compleja, simplifiquemos. Todo el grupo de subprocesos significa tener un número determinado de trabajadores ejecutándose simultáneamente. En realidad, solo podemos modificar algunas líneas de código del ejemplo lineal para obtener un ejemplo de subprocesos múltiples. El siguiente código encontrará cuántos núcleos tiene (si su navegador es compatible con esto), o predeterminado a 4. Encontré que este código corría aproximadamente 6 veces más rápido que el original en mi máquina con 8 núcleos.

ThreadPool.html

<!DOCTYPE html> <html> <head> <title>Thread Pool</title> </head> <body> <pre id="debug"></pre> <script type="text/javascript"> var debug = document.getElementById(''debug''); var maxWorkers = navigator.hardwareConcurrency || 4; var totalWorkers = 250; var index = 0; var start = (new Date).getTime(); function createWorker() { var worker = new Worker(''genericWorker.js''); worker.onmessage = function(event) { debug.appendChild(document.createTextNode(''worker.onmessage i = '' + event.data + ''/n'')); worker.terminate(); if (index < totalWorkers) createWorker(); else if(--maxWorkers === 0) alert((new Date).getTime() - start); }; worker.postMessage(index++); // start the worker. } for(var i = 0; i < maxWorkers; i++) createWorker(); </script> </body> <html>

Otros metodos

Método 3 (Trabajador individual, tarea repetida)

En su ejemplo, está usando el mismo trabajador una y otra vez. Sé que estás simplificando un caso de uso probablemente más complejo, pero algunas personas que lo verán verán esto y aplicarán este método cuando podrían estar usando solo un trabajador para todas las tareas.

Esencialmente, crearemos una instancia de un trabajador, enviaremos datos, esperaremos datos y luego repetiremos los pasos de envío / espera hasta que todos los datos hayan sido procesados.

En mi computadora, esto funciona aproximadamente al doble de la velocidad del grupo de subprocesos. Eso realmente me sorprendió. Pensé que la sobrecarga del grupo de subprocesos habría causado que fuera más lento que solo la mitad de la velocidad.

RepeatedWorker.html

<!DOCTYPE html> <html> <head> <title>Repeated Worker</title> </head> <body> <pre id="debug"></pre> <script type="text/javascript"> var debug = document.getElementById(''debug''); var totalWorkers = 250; var index = 0; var start = (new Date).getTime(); var worker = new Worker(''genericWorker.js''); function runWorker() { worker.onmessage = function(event) { debug.appendChild(document.createTextNode(''worker.onmessage i = '' + event.data + ''/n'')); if (index < totalWorkers) runWorker(); else { alert((new Date).getTime() - start); worker.terminate(); } }; worker.postMessage(index++); // start the worker. } runWorker(); </script> </body> <html>

Método 4 (Trabajador repetido con grupo de subprocesos)

Ahora, ¿y si combinamos el método anterior con el método de grupo de subprocesos? Teóricamente, debería funcionar más rápido que el anterior. Curiosamente, funciona a casi la misma velocidad que el anterior en mi máquina.

Tal vez sea la carga adicional de enviar la referencia del trabajador cada vez que se llame. Tal vez los trabajadores adicionales sean despedidos durante la ejecución (solo un trabajador no será despedido antes de que tengamos el tiempo). Quién sabe. Descubrir esto es un trabajo para otro momento.

RepeatedThreadPool.html

<!DOCTYPE html> <html> <head> <title>Repeated Thread Pool</title> </head> <body> <pre id="debug"></pre> <script type="text/javascript"> var debug = document.getElementById(''debug''); var maxWorkers = navigator.hardwareConcurrency || 4; var totalWorkers = 250; var index = 0; var start = (new Date).getTime(); function runWorker(worker) { worker.onmessage = function(event) { debug.appendChild(document.createTextNode(''worker.onmessage i = '' + event.data + ''/n'')); if (index < totalWorkers) runWorker(worker); else { if(--maxWorkers === 0) alert((new Date).getTime() - start); worker.terminate(); } }; worker.postMessage(index++); // start the worker. } for(var i = 0; i < maxWorkers; i++) runWorker(new Worker(''genericWorker.js'')); </script> </body> <html>

Ahora para un mundo real shtuff

¿Recuerdas que dije que estaba usando trabajadores para implementar complementos de terceros en mi código? Estos complementos tienen un estado para realizar un seguimiento. Podría iniciar los complementos y esperar que no carguen demasiado para que la aplicación se bloquee, o podría hacer un seguimiento del estado del complemento en mi hilo principal y enviar ese estado nuevamente al complemento si el complemento necesita ser recargado. Me gusta más el segundo.

Había escrito varios ejemplos más de trabajadores con estado, sin estado y de restablecimiento del estado, pero le evitaré la agonía y solo haré algunas explicaciones breves y algunos fragmentos más cortos.

En primer lugar, un trabajador con estado simple se ve así:

StatefulWorker.js

var i = 0; self.onmessage = function(e) { switch(e.data) { case ''increment'': self.postMessage(++i); break; case ''decrement'': self.postMessage(--i); break; } };

Hace alguna acción basada en el mensaje que recibe y contiene datos internamente. Esto es genial. Permite que los desarrolladores de complementos de mah tengan control total sobre sus complementos. La aplicación principal ejemplifica su complemento una vez, y luego enviará mensajes para que realicen alguna acción.

El problema aparece cuando queremos cargar varios complementos a la vez. No podemos hacer eso, entonces, ¿qué podemos hacer?

Pensemos en algunas soluciones.

Solución 1 (sin estado)

Hagamos que estos complementos sean sin estado. Básicamente, cada vez que queremos que el complemento haga algo, nuestra aplicación debe crear una instancia del complemento y luego enviar datos en función de su estado anterior.

datos enviados

{ action: ''increment'', value: 7 }

StatelessWorker.js

self.onmessage = function(e) { switch(e.data.action) { case ''increment'': e.data.value++; break; case ''decrement'': e.data.value--; break; } self.postMessage({ value: e.data.value, i: e.data.i }); };

Esto podría funcionar, pero si estamos tratando con una buena cantidad de datos, esto comenzará a parecer una solución menos que perfecta. Otra solución similar podría ser tener varios trabajadores más pequeños para cada complemento y enviar solo una pequeña cantidad de datos desde y hacia cada uno, pero también me inquieta.

Solución 2 (Restaurar Estado)

¿Qué pasa si tratamos de mantener al trabajador en la memoria el mayor tiempo posible, pero si lo perdemos, podemos restablecer su estado? Podemos utilizar algún tipo de programador para ver qué complementos ha estado utilizando el usuario (y quizás algunos algoritmos sofisticados para adivinar qué usará el usuario en el futuro) y mantenerlos en la memoria.

Lo bueno de esto es que ya no estamos mirando a un trabajador por núcleo. Como la mayor parte del tiempo que el trabajador está activo estará inactivo, solo debemos preocuparnos por la memoria que ocupa. Para un buen número de trabajadores (10 a 20 más o menos), esto no será sustancial en absoluto. Podemos mantener cargados los complementos primarios, mientras que los que no se utilizan se cambian con la frecuencia necesaria. Todos los complementos seguirán necesitando algún tipo de restauración de estado.

Usemos el siguiente trabajador y supongamos que enviamos ''incremento'', ''disminución'' o un entero que contenga el estado en el que se supone que debe estar.

StateRestoreWorker.js

var i = 0; self.onmessage = function(e) { switch(e.data) { case ''increment'': self.postMessage(++i); break; case ''decrement'': self.postMessage(--i); break; default: i = e.data; } };

Todos estos son ejemplos bastante simples, pero espero haber ayudado a comprender los métodos para utilizar múltiples trabajadores de manera eficiente. Lo más probable es que esté escribiendo un programador y un optimizador para estas cosas, pero quién sabe cuándo llegaré a ese punto.

¡Buena suerte y feliz codificación!


La forma en que encadena a sus Trabajadores en la solución n. ° 1 impugna al recolector de elementos no utilizados para terminar las instancias de Trabajador porque todavía tiene una referencia a ellos en el ámbito de su función de devolución de llamada onmessage.

Dale una oportunidad con este código:

<script type="text/javascript"> var worker; $(document).ready(function(){ createWorker(0); }); function createWorker(i) { worker = new Worker(''test.worker.js''); worker.onmessage = handleMessage; worker.postMessage(i); // start the worker. } function handleMessage(event) { var index = event.data; $("#debug").append(''worker.onmessage i = '' + index + "<br>"); if ( index < 25) { index++; createWorker(index); } }; </script> </head> <body> <div id="debug"></div>


Mi experiencia es que demasiados trabajadores (> 100) disminuyen el rendimiento. En mi caso, FF se volvió muy lento e incluso Chrome se bloqueó. Comparé variantes con diferentes cantidades de trabajadores (1, 2, 4, 8, 16, 32). El trabajador realizó un cifrado de una cadena. Resultó que 8 era la cantidad óptima de trabajadores, pero eso podría diferir, dependiendo del problema que el trabajador tiene que resolver.

Construí un pequeño marco para abstraer de la cantidad de trabajadores. Las llamadas a los trabajadores se crean como tareas. Si el número máximo permitido de trabajadores está ocupado, una nueva tarea se pone en cola y se ejecuta más tarde.

Resultó que es muy importante reciclar a los trabajadores en ese enfoque. Debe mantenerlos en una agrupación cuando están inactivos, pero no llame a Trabajador nuevo (...) con demasiada frecuencia. Incluso si los trabajadores son despedidos por worker.terminate () parece que hay una gran diferencia en el rendimiento entre crear / terminar y reciclar trabajadores.


Pregunta anterior, pero aparece en una búsqueda, entonces ... Hay un límite configurable en Firefox. Si busca en about:config (poner como dirección en la barra de direcciones de FF) y busca ''trabajador'', verá varias configuraciones, incluida esta:

dom.workers.maxPerDomain

Establecer en 20 por defecto. Haga doble clic en la línea y cambie la configuración. Tendrá que reiniciar el navegador.