¿Por qué JavaScript no admite subprocesos múltiples?

269

¿Es una decisión de diseño deliberada o un problema con nuestros navegadores actuales que se rectificará en las próximas versiones?

Niyaz
fuente
3
Consulte también las respuestas a la pregunta de JavaScript y subprocesos para obtener información sobre los trabajadores web / subprocesos de trabajo.
Sam Hasler
115
Hola, compañero de Google. Puede notar que todo aquí parece estar bastante anticuado (tenga en cuenta que esta pregunta se hizo hace más de 5 años). Desde que se hizo, los navegadores web han adquirido algunas capacidades que, por lo que puedo decir, son más o menos multiproceso. Eche un vistazo a Web Workers: msdn.microsoft.com/en-us/hh549259.aspx
ArtOfWarfare
2
Multithread.js envuelve Web Workers y permite un multihilo fácil en JS. Funciona en todos los nuevos navegadores, incluido iOS Safari. :)
kwh
1
Posible duplicado de JavaScript y subprocesos
Matt

Respuestas:

194

JavaScript no admite subprocesos múltiples porque el intérprete de JavaScript en el navegador es un subproceso único (AFAIK). Incluso Google Chrome no permitirá que el JavaScript de una sola página web se ejecute simultáneamente, ya que esto causaría problemas masivos de concurrencia en las páginas web existentes. Todo lo que Chrome hace es separar múltiples componentes (diferentes pestañas, complementos, etc.) en procesos separados, pero no puedo imaginar una sola página que tenga más de un hilo de JavaScript.

Sin embargo, puede usar, como se sugirió, setTimeoutpara permitir algún tipo de programación y concurrencia "falsa". Esto hace que el navegador recupere el control del hilo de renderizado e inicie el código JavaScript proporcionado asetTimeout después del número de milisegundos dado. Esto es muy útil si desea permitir que la ventana gráfica (lo que ve) se actualice mientras realiza operaciones en ella. Simplemente recorrer, por ejemplo, las coordenadas y actualizar un elemento en consecuencia, solo le permitirá ver las posiciones de inicio y finalización, y nada en el medio.

Utilizamos una biblioteca de abstracción en JavaScript que nos permite crear procesos y subprocesos que son administrados por el mismo intérprete de JavaScript. Esto nos permite ejecutar acciones de la siguiente manera:

  • Proceso A, Hilo 1
  • Proceso A, Hilo 2
  • Proceso B, Hilo 1
  • Proceso A, Hilo 3
  • Proceso A, Hilo 4
  • Proceso B, Hilo 2
  • Pausa proceso A
  • Proceso B, Hilo 3
  • Proceso B, Hilo 4
  • Proceso B, Hilo 5
  • Iniciar proceso A
  • Proceso A, Hilo 5

Esto permite alguna forma de programación y simula paralelismo, inicio y detención de subprocesos, etc., pero no será verdadero subprocesamiento múltiple. No creo que alguna vez se implemente en el lenguaje en sí, ya que el verdadero subproceso múltiple solo es útil si el navegador puede ejecutar una sola página con subprocesos múltiples (o incluso más de un núcleo), y las dificultades son mucho mayores. que las posibilidades extra.

Para el futuro de JavaScript, mira esto: https://developer.mozilla.org/presentations/xtech2006/javascript/

Kamiel Wanrooij
fuente
73
Creo que nunca implementado es una visión demasiado estrecha. Garantizo que las aplicaciones web eventualmente podrán ser realmente multiproceso (es lógico, ya que las aplicaciones web se vuelven más dominantes y el hardware se vuelve más paralelo), y como lo veo, ya que JavaScript es el lenguaje de facto del desarrollo web, eventualmente tendrá que soportar multihilo o ser reemplazado por algo que lo haga.
devios1
66
Probablemente nunca sea una declaración demasiado audaz :) pero sigo pensando que las ventajas de javascript multiproceso verdadero no son factibles en el futuro previsible;)
Kamiel Wanrooij
55
Aunque yo diría que los trabajadores web son más concurrentes a través de un modelo de proceso que un modelo de hilo. Los trabajadores web utilizan el paso de mensajes como medio de comunicación, que es una solución elegante a los problemas de concurrencia "habituales" en aplicaciones multiproceso. No estoy seguro de si realmente pueden operar en los mismos objetos que la página principal al mismo tiempo. No pueden acceder al DOM hasta donde yo sé. Sin embargo, la mayor parte de esto es semántica, los trabajadores web parecen prometedores para todos los efectos.
Kamiel Wanrooij
las dificultades son mucho mayores que las posibilidades adicionales. No estoy seguro si piensa en todas las posibilidades adicionales. Estoy pensando especialmente en casos en los que webgl se usa como en juegos o visualizaciones gráficas. Por ejemplo, considere la nueva versión 3D de Google Maps. En ciudades con muchos modelos 3D, mi PC necesita ~ 2 minutos para cargar todo cuando hay que renderizar muchas casas. En ciertos ángulos, ni mi tarjeta gráfica ni mi red están funcionando a su capacidad. Pero 1 de los 8 procesadores está al 100%. El subprocesamiento múltiple también es una gran preocupación en términos de fps, como muestra este ejemplo: youtube.com/watch?v=sJ2p982cZFc
Scindix el
25

El subprocesamiento múltiple de JavaScript (con algunas limitaciones) está aquí. Google implementó trabajadores para Gears, y los trabajadores se están incluyendo con HTML5. La mayoría de los navegadores ya han agregado soporte para esta función.

La seguridad de los subprocesos de los datos está garantizada porque todos los datos comunicados al / del trabajador se serializan / copian.

Para más información, lea:

http://www.whatwg.org/specs/web-workers/current-work/

http://ejohn.org/blog/web-workers/

Neil
fuente
8
Pero, ¿no se trata más de un enfoque multiproceso que de varios subprocesos? Se sabe que los subprocesos funcionan dentro de un único montón.
beefeather
1
@beefeather, eso es cierto. Es más un enfoque de proceso.
Neil
23

Tradicionalmente, JS estaba destinado a piezas de código cortas y de ejecución rápida. Si tenía cálculos importantes, lo hizo en un servidor: la idea de una aplicación JS + HTML que se ejecutara en su navegador durante largos períodos de tiempo haciendo cosas no triviales era absurda.

Por supuesto, ahora tenemos eso. Sin embargo, los navegadores tardarán un poco en ponerse al día: la mayoría de ellos se han diseñado en torno a un modelo de un solo subproceso, y cambiar eso no es fácil. Google Gears evita muchos problemas potenciales al requerir que la ejecución en segundo plano esté aislada: sin cambiar el DOM (ya que no es seguro para subprocesos), sin acceder a los objetos creados por el subproceso principal (ídem). Si bien es restrictivo, este será probablemente el diseño más práctico para el futuro cercano, tanto porque simplifica el diseño del navegador como porque reduce el riesgo involucrado en permitir que los codificadores JS sin experiencia jueguen con hilos ...

@marcio :

¿Por qué es esa una razón para no implementar multi-threading en Javascript? Los programadores pueden hacer lo que quieran con las herramientas que tienen.

Entonces, no les demos herramientas que sean tan fáciles de usar que cualquier otro sitio web que abra termine con mi navegador. Una implementación ingenua de esto lo llevaría directamente al territorio que causó tantos dolores de cabeza a MS durante el desarrollo de IE7: los autores de complementos jugaron rápido y suelto con el modelo de subprocesos, lo que resultó en errores ocultos que se hicieron evidentes cuando los ciclos de vida de los objetos cambiaron en el hilo primario . MALO. Si está escribiendo complementos ActiveX multiproceso para IE, supongo que viene con el territorio; no significa que deba ir más allá de eso.

Shog9
fuente
66
"reduce el riesgo involucrado> al permitir que los codificadores JS sin experiencia> jueguen con subprocesos" ¿Por qué es esa una razón para no implementar subprocesos múltiples en Javascript? Los programadores pueden hacer lo que quieran con las herramientas que tienen. Si es bueno o malo, es su problema. Con el modelo de proceso de Google Chrome, ni siquiera puede afectar a otras aplicaciones. :)
Marcio Aguiar
3
@ Shog9 - "No demos herramientas [a los programadores] que sean tan fáciles de usar que cualquier otro sitio web que abra termine con mi navegador". - ¿Qué? Según esa misma lógica, ningún lenguaje debería tener subprocesos múltiples, porque si ofrecieran que todos los demás programas que intentaste abrir se bloquearían. Excepto que no funciona de esa manera. El subproceso existe en la mayoría de los idiomas y la mayoría de los programadores novatos no lo tocan, y la mayoría de los que lo hacen no lo ponen en producción, y esas aplicaciones que nunca se vuelven populares o ampliamente utilizadas.
ArtOfWarfare
11

No sé la razón de esta decisión, pero sé que puede simular algunos de los beneficios de la programación multiproceso utilizando setTimeout. Puede dar la ilusión de múltiples procesos haciendo cosas al mismo tiempo, aunque en realidad, todo sucede en un hilo.

Simplemente haga que su función haga un poco de trabajo y luego llame a algo como:

setTimeout(function () {
    ... do the rest of the work...
}, 0);

Y cualquier otra cosa que necesite hacer (como actualizaciones de UI, imágenes animadas, etc.) sucederá cuando tengan la oportunidad.

pkaeding
fuente
En la mayoría de los casos, me gustaría usar un loopdentro, setTimeoutpero aparentemente eso no funciona. ¿Has hecho algo así o tienes un truco? un ejemplo sería para una matriz de 1000 elementos, espero usar dos para bucles dentro de dos setTimeoutllamadas, de modo que el primer bucle y el elemento de impresión 0..499, el segundo bucle y el elemento de impresión 500..999.
benjaminz
Por lo general, la técnica es salvar el estado y continuar. Por ejemplo, supongamos que desea imprimir de 0 a 1000, puede imprimir de 0 a 499 y luego hacer el truco setTimeout con el argumento 500. El código interno sabría tomar el argumento (500) y comenzar el ciclo desde allí.
Eyal
8

¿Quiere decir por qué el lenguaje no admite subprocesos múltiples o por qué los motores JavaScript en los navegadores no admiten subprocesos múltiples?

La respuesta a la primera pregunta es que JavaScript en el navegador debe ejecutarse en un entorno limitado y de forma independiente de la máquina / SO, agregar soporte de subprocesamiento múltiple complicaría el idioma y lo vincularía demasiado al SO.

mate b
fuente
6

Node.js 10.5+ admite subprocesos de trabajo como característica experimental (puede usarlo con - bandera de trabajador experimental habilitada): https://nodejs.org/api/worker_threads.html

Entonces, la regla es:

  • si necesita hacer operaciones vinculadas de E / S , use el mecanismo interno (también conocido como callback / promise / async-await)
  • Si necesita hacer operaciones vinculadas a la CPU , use hilos de trabajo.

Los hilos de trabajo están destinados a ser hilos de larga duración, lo que significa que genera un hilo de fondo y luego se comunica con él a través de la transmisión de mensajes.

De lo contrario, si necesita ejecutar una gran carga de CPU con una función anónima, puede ir a https://github.com/wilk/microjob , una pequeña biblioteca construida alrededor de hilos de trabajo.

Wilk
fuente
4

Tal como dijo Matt B, la pregunta no es muy clara. Suponiendo que está preguntando sobre el soporte de subprocesos múltiples en el idioma: porque no es necesario para el 99.999% de las aplicaciones que se ejecutan actualmente en el navegador. Si realmente lo necesita, existen soluciones alternativas (como usar window.setTimeout).

En general, el subprocesamiento múltiple es muy, muy, muy, muy, muy, muy difícil (¿dije que es difícil?) Acertar, a menos que establezca restricciones adicionales (como usar solo datos inmutables).

Pantera gris
fuente
3

Intel ha estado haciendo una investigación de código abierto sobre subprocesos múltiples en Javascript, se mostró recientemente en GDC 2012. Aquí está el enlace para el video . El grupo de investigación utilizó OpenCL, que se centra principalmente en conjuntos de chips Intel y el sistema operativo Windows. El proyecto tiene el nombre en código RiverTrail y el código está disponible en GitHub

Algunos enlaces más útiles:

Construyendo una autopista informática para aplicaciones web

Rohit Reddy Korrapolu
fuente
1

Son las implementaciones las que no admiten subprocesos múltiples. Actualmente, Google Gears proporciona una forma de utilizar algún tipo de concurrencia mediante la ejecución de procesos externos, pero eso es todo.

Se supone que el nuevo navegador que Google lanzará hoy (Google Chrome) ejecuta un código en paralelo separándolo en el proceso.

El lenguaje central, por supuesto, puede tener el mismo soporte que, por ejemplo, Java, pero el soporte para algo como la concurrencia de Erlang no está cerca del horizonte.

Greg Roberts
fuente
1

Javascript es un lenguaje de subproceso único. Esto significa que tiene una pila de llamadas y un montón de memoria. Como se esperaba, ejecuta el código en orden y debe terminar de ejecutar un código de pieza antes de pasar al siguiente. Es sincrónico, pero a veces eso puede ser dañino. Por ejemplo, si una función tarda un tiempo en ejecutarse o tiene que esperar algo, se congela todo mientras tanto.

Omar bakhsh
fuente
0

Por lo que he escuchado, Google Chrome tendrá javascript multiproceso, por lo que es un problema de "implementaciones actuales".

BlaM
fuente
0

Sin el soporte de idioma adecuado para la sincronización de subprocesos, ni siquiera tiene sentido que las nuevas implementaciones lo intenten. Las aplicaciones JS complejas existentes (por ejemplo, cualquier cosa que use ExtJS) probablemente se bloquee inesperadamente, pero sin una synchronizedpalabra clave o algo similar, también sería muy difícil o incluso imposible escribir nuevos programas que se comporten correctamente.

Erich Kitzmueller
fuente
-1

Sin embargo, puede usar la función eval para llevar la concurrencia EN ALGUNA EXTENSIÓN

/* content of the threads to be run */
var threads = [
        [
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');"
        ],
        [
            "document.write('Bar <br/>');",
            "document.write('Bar <br/>');",
            "document.write('Bar <br/>');",
            "document.write('Bar <br/>');",
            "document.write('Bar <br/>');",
            "document.write('Bar <br/>');",
            "document.write('Bar <br/>');",
            "document.write('Bar <br/>');",
            "document.write('Bar <br/>');"
        ]
    ];

window.onload = function() {
    var lines = 0, quantum = 3, max = 0;

    /* get the longer thread length */
    for(var i=0; i<threads.length; i++) {
        if(max < threads[i].length) {
            max = threads[i].length;
        }
    }

    /* execute them */
    while(lines < max) {
        for(var i=0; i<threads.length; i++) {
            for(var j = lines; j < threads[i].length && j < (lines + quantum); j++) {
                eval(threads[i][j]);
            }
        }
        lines += quantum;
    }
}
Madhusoodan P
fuente
-2

El subprocesamiento múltiple con javascript es claramente posible utilizando los trabajadores web traídos por HTML5.

La principal diferencia entre los trabajadores web y un entorno estándar de subprocesos múltiples es que los recursos de memoria no se comparten con el subproceso principal, una referencia a un objeto no es visible de un subproceso a otro. Los hilos se comunican intercambiando mensajes, por lo tanto, es posible implementar un algoritmo de sincronización y llamada de método concurrente siguiendo un patrón de diseño controlado por eventos.

Existen muchos marcos que permiten estructurar la programación entre subprocesos, entre ellos OODK-JS, un marco OOP js que admite programación concurrente https://github.com/GOMServices/oodk-js-oop-for-js

revs OBDM
fuente
55
Compartir memoria es la definición exacta de un subproceso opuesto a un proceso separado (por ejemplo, fork () vs exec ()). Los hilos pueden compartir objetos, los procesos deben usar IPC. Los trabajadores web no son multiproceso.
felixfbecker