He estado trabajando en una implementación de tiempo de ejecución de JavaScript multiproceso durante la semana pasada. Tengo una prueba de concepto hecha en C ++ usando JavaScriptCore y boost.
La arquitectura es simple: cuando el tiempo de ejecución termina de evaluar el script principal, se inicia y se une a un grupo de subprocesos, que comienza a seleccionar tareas de una cola de prioridad compartida, si dos tareas intentan acceder a una variable al mismo tiempo, se marca atómica y compiten por el acceso .
El problema es que cuando muestro este diseño a un programador de JavaScript recibo comentarios extremadamente negativos, y no tengo idea de por qué. Incluso en privado, todos dicen que JavaScript está destinado a ser de un solo subproceso, que las bibliotecas existentes tendrían que reescribirse, y que los gremlins generarán y se comerán a todos los seres vivos si sigo trabajando en esto.
Originalmente, también tenía una implementación de rutina nativa (usando contextos de impulso), pero tuve que deshacerme de ella (JavaScriptCore es pedante sobre la pila), y no quería arriesgar su ira, así que decidí no mencionarlo.
¿Qué piensas? ¿JavaScript está destinado a ser de un solo subproceso, y debe dejarse solo? ¿Por qué todos están en contra de la idea de un tiempo de ejecución de JavaScript concurrente?
Editar: El proyecto ahora está en GitHub , experimente con usted mismo y hágame saber lo que piensa.
La siguiente es una imagen de las promesas que se ejecutan en todos los núcleos de CPU en paralelo sin contención:
fuente
Respuestas:
1) El subprocesamiento múltiple es extremadamente difícil y, desafortunadamente, la forma en que has presentado esta idea hasta ahora implica que estás subestimando severamente lo difícil que es.
Por el momento, parece que simplemente está "agregando hilos" al idioma y preocupándose por cómo corregirlo y realizarlo más tarde. En particular:
Agregar hilos a Javascript sin una "solución para el problema de sincronización" sería como agregar enteros a Javascript sin una "solución para el problema de adición". Es tan fundamental para la naturaleza del problema que básicamente no tiene sentido ni siquiera discutir si vale la pena agregar múltiples subprocesos sin una solución específica en mente, sin importar cuán mal lo deseemos.
Además, hacer que todas las variables sean atómicas es el tipo de cosa que probablemente haga que un programa multiproceso funcione peor que su contraparte de un solo hilo, lo que hace que sea aún más importante probar el rendimiento en programas más realistas y ver si está ganando algo o no.
Tampoco me queda claro si está tratando de mantener los hilos ocultos del programador node.js o si planea exponerlos en algún momento, creando efectivamente un nuevo dialecto de Javascript para la programación multiproceso. Ambas opciones son potencialmente interesantes, pero parece que aún no has decidido a cuál estás apuntando.
Entonces, en este momento, le está pidiendo a los programadores que consideren cambiar de un entorno de subproceso único a un nuevo entorno de subprocesos múltiples que no tiene solución para el problema de sincronización y no hay evidencia de que mejore el rendimiento en el mundo real, y aparentemente no hay un plan para resolver esos problemas.
Probablemente por eso la gente no te toma en serio.
2) La simplicidad y robustez del bucle de evento único es una gran ventaja.
Los programadores de Javascript saben que el lenguaje Javascript está "a salvo" de las condiciones de carrera y otros errores extremadamente insidiosos que afectan a toda la programación genuinamente multiproceso. El hecho de que necesiten argumentos sólidos para convencerlos de que renuncien a la seguridad no los hace de mente cerrada, los hace responsables.
A menos que pueda mantener esa seguridad de alguna manera, cualquiera que desee cambiar a un nodo multiproceso .js probablemente sería mejor cambiar a un lenguaje como Go diseñado desde cero para aplicaciones multiproceso.
3) Javascript ya admite "subprocesos en segundo plano" (WebWorkers) y programación asincrónica sin exponer directamente la gestión de subprocesos al programador.
Esas características ya resuelven muchos de los casos de uso comunes que afectan a los programadores de Javascript en el mundo real, sin renunciar a la seguridad del bucle de eventos únicos.
¿Tiene en mente algunos casos de uso específicos que estas características no resuelven y para los que los programadores de Javascript quieren una solución? Si es así, sería una buena idea presentar su node.js multiproceso en el contexto de ese caso de uso específico.
PD ¿Qué me convencería de intentar cambiar a una implementación de node.js multiproceso?
Escriba un programa no trivial en Javascript / node.js que cree que se beneficiaría de un subprocesamiento múltiple genuino. Realice pruebas de rendimiento en este programa de muestra en el nodo normal y en su nodo multiproceso. Muéstreme que su versión mejora el rendimiento del tiempo de ejecución, la capacidad de respuesta y el uso de múltiples núcleos en un grado significativo, sin introducir errores ni inestabilidad.
Una vez que hayas hecho eso, creo que verás a las personas mucho más interesadas en esta idea.
fuente
Solo adivinando aquí para demostrar un problema en su enfoque. No puedo probarlo con la implementación real ya que no hay ningún enlace en ninguna parte ...
Yo diría que es porque los invariantes no siempre se expresan por el valor de una variable, y 'una variable' no es suficiente para ser el alcance de un bloqueo en el caso general. Por ejemplo, imagine que tenemos un invariante que
a+b = 0
(el saldo de un banco con dos cuentas). Las dos funciones siguientes aseguran que el invariante se mantenga siempre al final de cada función (la unidad de ejecución en JS de un solo subproceso).Ahora, en su mundo multiproceso, ¿qué sucede cuando dos hilos se ejecutan
withdraw
ydeposit
al mismo tiempo? Gracias Murphy ...(Es posible que tenga un código que trate a + = y - = especialmente, pero eso no es de ayuda. En algún momento, tendrá un estado local en una función, y sin forma de 'bloquear' dos variables al mismo tiempo, su invariante ser violado)
EDITAR: si su código es semánticamente equivalente al código Go en https://gist.github.com/thriqon/f94c10a45b7e0bf656781b0f4a07292a , mi comentario es preciso ;-)
fuente
Hace aproximadamente una década, Brendan Eich (el inventor de JavaScript) escribió un ensayo llamado Threads Suck , que es definitivamente uno de los pocos documentos canónicos de la mitología del diseño de JavaScript.
Si es correcto es otra pregunta, pero creo que tuvo una gran influencia en cómo piensa la comunidad JavaScript sobre la concurrencia.
fuente
El acceso atómico no se traduce en un comportamiento seguro para subprocesos.
Un ejemplo es cuando una estructura de datos global debe ser inválida durante una actualización, como volver a mostrar un hashmap (al agregar una propiedad a un objeto, por ejemplo) u ordenar una matriz global. Durante ese tiempo no puede permitir que ningún otro hilo acceda a la variable. Esto básicamente significa que necesita detectar los ciclos completos de lectura-actualización-escritura y bloquearlo. Si la actualización no es trivial, terminará en un territorio problemático detenido.
Javascript ha sido de un solo subproceso y sandboxed desde el principio y todo el código está escrito teniendo en cuenta estos supuestos.
Esto tiene una gran ventaja con respecto a los contextos aislados y permite que 2 contextos separados se ejecuten en hilos diferentes. También quiero decir que las personas que escriben JavaScript no necesitan saber cómo lidiar con las condiciones de carrera y otras fallas de varios hilos.
fuente
¿Su enfoque va a mejorar significativamente el rendimiento?
Dudoso. Realmente necesitas probar esto.
¿Su enfoque hará que sea más fácil / rápido escribir código?
Definitivamente no, el código multiproceso es muchas veces más difícil de corregir que el código de subproceso único.
¿Su enfoque será más robusto?
Los puntos muertos, las condiciones de carrera, etc. son una pesadilla para solucionar.
fuente
Su implementación no se trata solo de introducir concurrencia, sino de introducir una forma específica de implementar concurrencia, es decir, concurrencia por estado mutable compartido. En el transcurso de la historia, las personas han usado este tipo de concurrencia y esto ha llevado a muchos tipos de problemas. Por supuesto, puede crear programas simples que funcionen perfectamente con el uso de concurrencia de estado mutable compartida, pero la prueba real de cualquier mecanismo no es lo que puede hacer, sino que puede escalar a medida que el programa se vuelve complejo y se agregan más y más funciones al programa. Recuerde que el software no es algo estático que construye una vez y termina con él, sino que sigue evolucionando con el tiempo y si algún mecanismo o concepto puede '
Puede ver otros modelos de concurrencia (por ejemplo, pasar mensajes) para ayudarlo a descubrir qué tipo de beneficios proporcionan esos modelos.
fuente
Esto es necesario La falta de un mecanismo de concurrencia de bajo nivel en el nodo js limita sus aplicaciones en campos como matemática y bioinformática, etc. Además, la concurrencia con hilos no necesariamente entra en conflicto con el modelo de concordancia predeterminado utilizado en el nodo. Existen semánticas bien conocidas para el subprocesamiento en un entorno con un bucle de eventos principal, como los marcos ui (y nodejs), y aunque definitivamente son demasiado complejos para la mayoría de las situaciones, todavía tienen usos válidos.
Claro, su aplicación web promedio no requerirá hilos, pero intente hacer algo un poco menos convencional, y la falta de una primitiva de concurrencia de bajo nivel de sonido lo alejará rápidamente de algo que sí lo ofrece.
fuente
Realmente creo que es porque es una idea diferente y poderosa. Estás yendo en contra de los sistemas de creencias. Las cosas se vuelven aceptadas o populares a través de la red y no afectan por méritos. Además, nadie quiere adaptarse a una nueva pila. Las personas rechazan automáticamente cosas que son demasiado diferentes.
Si puede encontrar una manera de convertirlo en un módulo npm normal que parezca poco probable, entonces puede hacer que algunas personas lo usen.
fuente