¿Son las piscinas gorutinas go-langs solo hilos verdes?

47

El comentarista aquí ofrece las siguientes críticas a los hilos verdes:

Inicialmente me vendieron el modelo N: M como un medio para tener una programación dirigida por eventos sin el infierno de devolución de llamadas. Puede escribir código que parezca un viejo código de procedimiento pero debajo hay magia que usa el cambio de tareas en el espacio del usuario cada vez que algo se bloquea. Suena genial. El problema es que terminamos resolviendo la complejidad con más complejidad. swapcontext () y family son bastante estrictos, la complejidad proviene de otros lugares no deseados.

De repente, se ve obligado a escribir un planificador de espacio de usuario y adivinar qué es realmente difícil escribir un planificador que haga un mejor trabajo que los cronogramas de Linux que tienen muchos años de esfuerzos. Ahora desea que su programación maneje N hilos verdes a M hilos físicos, por lo que debe preocuparse por la sincronización. La sincronización trae problemas de rendimiento, así que comienzas ahora que estás en un nuevo agujero de conejo sin cerradura. Crear un planificador correcto altamente concurrente no es tarea fácil.

Otra crítica está aquí :

Un solo proceso que simula múltiples hilos tiene muchos problemas. Una de ellas es que todos los hilos falsos se bloquean en cualquier falla de página.

Mi pregunta es: ¿ son las gorutinas de go-lang (para un grupo predeterminado) solo hilos verdes? Si es así, ¿abordan las críticas anteriores?

ojo de halcón
fuente

Respuestas:

67

Solo soy un usuario casual de Go, así que tome lo siguiente con un grano de sal.

Wikipedia define hilos verdes como "hilos programados por una máquina virtual (VM) en lugar de ser nativos por el sistema operativo subyacente". Los subprocesos verdes emulan entornos multiproceso sin depender de las capacidades nativas del sistema operativo, y se administran en el espacio del usuario en lugar del espacio del kernel, lo que les permite trabajar en entornos que no tienen soporte de subprocesos nativos.

Go (o más exactamente las dos implementaciones existentes) es un lenguaje que solo produce código nativo, no utiliza una VM. Además, el planificador en las implementaciones de tiempo de ejecución actuales se basa en subprocesos a nivel del sistema operativo (incluso cuando GOMAXPROCS = 1). Así que creo que hablar de hilos verdes para el modelo Go es un poco abusivo.

Ir a la gente ha acuñado el término gorutina especialmente para evitar la confusión con otros mecanismos de concurrencia (como las rutinas o hilos o procesos ligeros).

Por supuesto, Go admite un modelo de subprocesos M: N, pero se parece mucho más al modelo de proceso Erlang que al modelo de subproceso verde Java.

Aquí hay algunos beneficios del modelo Go sobre hilos verdes (como se implementó en la primera JVM):

  • Se pueden usar múltiples núcleos o CPU de manera efectiva, de manera transparente para el desarrollador. Con Go, el desarrollador debe ocuparse de la concurrencia. El tiempo de ejecución de Go se encargará del paralelismo. Las implementaciones de hilos verdes de Java no se escalaron en múltiples núcleos o CPU.

  • El sistema y las llamadas C no bloquean el programador (todas las llamadas al sistema, no solo las que admiten E / S multiplexadas en bucles de eventos). Las implementaciones de subprocesos verdes podrían bloquear todo el proceso cuando se realizó una llamada al sistema de bloqueo.

  • Copias o pilas segmentadas. En Go, no es necesario proporcionar un tamaño de pila máximo para la goroutine. La pila crece de forma incremental según sea necesario. Una consecuencia es que una rutina no requiere mucha memoria (4KB-8KB), por lo que una gran cantidad de ellas puede generarse felizmente. El uso de goroutina puede por lo tanto ser generalizado.

Ahora, para abordar las críticas:

  • Con Go, no tiene que escribir un planificador de espacio de usuario: ya se proporciona con el tiempo de ejecución. Es un software complejo, pero es el problema de los desarrolladores de Go, no de los usuarios de Go. Su uso es transparente para los usuarios de Go. Entre los desarrolladores de Go, Dmitri Vyukov es un experto en programación sin bloqueo / sin espera, y parece estar especialmente interesado en abordar los posibles problemas de rendimiento del programador. La implementación actual del planificador no es perfecta, pero mejorará.

  • La sincronización trae problemas de rendimiento y complejidad: esto también es parcialmente cierto con Go. Pero tenga en cuenta que el modelo Go intenta promover el uso de canales y una descomposición limpia del programa en goroutines concurrentes para limitar la complejidad de la sincronización (es decir, compartir datos mediante la comunicación, en lugar de compartir la memoria para comunicarse). Por cierto, la implementación Go de referencia proporciona una serie de herramientas para abordar problemas de rendimiento y concurrencia, como un generador de perfiles y un detector de carrera .

  • Con respecto a la falla de la página y la "falsificación de múltiples hilos", tenga en cuenta que Go puede programar goroutine en múltiples hilos del sistema. Cuando un hilo se bloquea por cualquier motivo (error de página, bloqueo de llamadas del sistema), no impide que los otros hilos continúen programando y ejecutando otras rutinas. Ahora, es cierto que un error de página bloqueará el hilo del sistema operativo, con todas las rutinas supuestamente programadas en este hilo. Sin embargo, en la práctica, no se supone que la memoria de almacenamiento dinámico Go se intercambie. Esto sería lo mismo en Java: los lenguajes recolectados de basura no se adaptan muy bien a la memoria virtual de todos modos. Si su programa debe manejar la falla de la página de una manera elegante, probablemente porque tiene que administrar algo de memoria fuera del montón. En ese caso,

Entonces, en mi opinión, las gorutinas no son hilos verdes, y el lenguaje Go y la implementación actual abordan principalmente estas críticas.

Didier Spezia
fuente
1
Una respuesta excelente y detallada a la pregunta :)
Tuxdude
1
Me encanta esta respuesta, pero ¿tiene alguna referencia sobre cómo / cuándo se crean los hilos del sistema operativo?
Lars
1
¡Uno de los mayores inconvenientes de Go Language es que crea un hilo Kernel para cada llamada al sistema de bloqueo!
user1870400
8
Tenga en cuenta que el artículo "hilo verde" en Wikipedia se ha cambiado para indicar "hilos programados por una biblioteca de tiempo de ejecución o máquina virtual (VM)"; lo que significa que, según esa definición, su respuesta ya no sería correcta, ya que Go runtime realiza la programación / gestión. Creo que es más útil definir hilos verdes como hilos de espacio de usuario en contraste con hilos de SO. Y luego, sí, las gorutinas son hilos verdes con seguridad.
mknecht
1
Segundo que @mknecht. No se trata de la VM, se trata del tiempo de ejecución. Y Go definitivamente tiene un tiempo de ejecución. (que gestiona el modelo de subprocesos y la recolección de basura).
Tim Harper