En programación informática , un hilo virtual es un hilo gestionado por una biblioteca de tiempo de ejecución o una máquina virtual (VM) que se comporta como un hilo del núcleo para el código que se ejecuta en él, aunque requiere muchos menos recursos que este último.
Los subprocesos virtuales permiten decenas de millones de tareas y eventos con prioridad en un ordenador de consumo de 2021, [ 1 ] en comparación con los pocos miles de subprocesos del sistema operativo . [ 2 ] La ejecución con prioridad [ 3 ] es importante para obtener mejoras de rendimiento mediante el paralelismo y tiempos de respuesta rápidos con prioridad para decenas de millones de eventos.
Las construcciones anteriores que no son o no siempre son preventivas, como las corrutinas , los hilos ligeros o Node.js , que en su mayoría es de un solo hilo, introducen retrasos en la respuesta a eventos asíncronos, como cada solicitud entrante en una aplicación de servidor. [ 4 ]
Definición
Los hilos virtuales son preventivos
- Para un buen rendimiento de respuesta, un hilo virtual puede reaccionar a eventos sin la intervención del programador o antes de concluir una tarea en curso.
- La prioridad requiere conocimientos de programación multihilo para evitar escrituras incompletas, condiciones de carrera y escrituras invisibles por parte de otros hilos.
Los hilos virtuales pueden saltar por encima de las unidades de ejecución de todos los procesadores y núcleos.
- Esto permite un mejor aprovechamiento del hardware disponible.
- Go (desde la versión 1.18) utiliza colas de hilos virtuales por unidad de ejecución . Existen hilos virtuales adicionales no asignados a una unidad de ejecución, y una unidad de ejecución puede robar hilos virtuales de otra unidad de ejecución. [ 5 ]
Los hilos virtuales no requieren ninguna intervención por parte del programador ni de ninguna otra acción similar.
- Los hilos virtuales parecen ejecutarse de forma continua hasta que finalizan su ejecución o se detienen ante un bloqueo de sincronización.
- A diferencia de las corrutinas, si un hilo virtual entra en un bucle infinito, no bloquea el programa. La ejecución continúa con una mayor carga de CPU, incluso si hay más hilos en bucle que unidades de ejecución disponibles.
Los hilos virtuales pueden llegar a ser decenas de millones al presentar pilas pequeñas y a menudo administradas.
- Esto permite utilizar muchísimos más hilos de ejecución de los que serían posibles utilizando los hilos del sistema operativo.
- Go 1.18 puede ejecutar 15 millones de hilos virtuales en un ordenador de consumo de 2021, es decir, unos 350 000 por gigabyte de memoria principal. Esto es posible gracias a que las goroutines tienen una pila redimensionable de menos de 3 KiB.
Los subprocesos virtuales se pueden asignar rápidamente.
- Debido a que la asignación de un hilo virtual supone una sobrecarga mínima con respecto a la asignación de memoria, se pueden asignar muy rápidamente.
- La puesta en marcha más rápida reduce la necesidad de contar con grupos de hilos pre-lanzados para hacer frente a aumentos repentinos del tráfico.
Los hilos virtuales comparten memoria como los hilos del sistema operativo.
- Al igual que los subprocesos del sistema operativo, los subprocesos virtuales comparten memoria entre los procesos y, por lo tanto, pueden compartir y acceder libremente a los objetos de memoria, sujetos a sincronización.
- Algunas arquitecturas de un solo hilo, como el motor V8 ECMAScript utilizado por Node.js, no aceptan fácilmente datos que el hilo en cuestión no haya asignado, lo que requiere el uso de tipos de datos especiales de copia cero al compartir datos entre hilos.
Los hilos virtuales ofrecen paralelismo, al igual que los hilos del sistema operativo.
- El paralelismo implica que varias instrucciones se ejecutan realmente al mismo tiempo, lo que normalmente conlleva un rendimiento mucho más rápido.
- Esto difiere de la concurrencia más simple, en la que una única unidad de ejecución ejecuta múltiples hilos compartidos en pequeños intervalos de tiempo. La división temporal hace que cada hilo parezca ejecutarse continuamente. Si bien la concurrencia es más fácil de implementar y programar, no ofrece ninguna mejora en el rendimiento.
Motivación
Los servidores Java han incorporado estructuras de software extensas y de alto consumo de memoria que permiten que docenas de subprocesos del sistema operativo, agrupados en un clúster, ejecuten miles de solicitudes por segundo de forma preventiva sin utilizar subprocesos virtuales. La clave del rendimiento reside en reducir la latencia inicial en el procesamiento de subprocesos y minimizar el tiempo de bloqueo de los subprocesos del sistema operativo. [ 6 ]
Los hilos virtuales aumentan la concurrencia posible en muchos órdenes de magnitud, mientras que el paralelismo real alcanzado está limitado por las unidades de ejecución disponibles y el procesamiento en paralelo que ofrecen los procesadores y núcleos de procesador actuales. En 2021, las computadoras de consumo suelen ofrecer un paralelismo de decenas de unidades de ejecución concurrentes. [ 7 ] Para aumentar el rendimiento mediante el paralelismo, el entorno de ejecución del lenguaje debe utilizar todo el hardware disponible, [ 8 ] no ser de un solo hilo o contar con sincronización global como el bloqueo global del intérprete .
El considerable aumento en la cantidad de elementos preemptivos que ofrecen los hilos virtuales se logra mediante la gestión de pilas de hilos redimensionables por parte del entorno de ejecución del lenguaje. [ 9 ] Estas pilas son de menor tamaño que las de los hilos del sistema operativo. El número máximo de hilos posible sin intercambio es proporcional a la cantidad de memoria principal. [ 10 ]
Para admitir hilos virtuales de manera eficiente, el entorno de ejecución del lenguaje debe reescribirse en gran medida para evitar que las llamadas bloqueantes retengan un hilo del sistema operativo asignado para ejecutar un hilo virtual [ 11 ] y para administrar las pilas de hilos. [ 12 ] Un ejemplo de una adaptación de un entorno de ejecución existente con hilos virtuales es el Proyecto Loom de Java . [ 13 ] Un ejemplo de un nuevo lenguaje diseñado para hilos virtuales es Go. [ 14 ]
Complejidad
Debido a que los hilos virtuales ofrecen paralelismo, el programador necesita tener conocimientos de programación multihilo y sincronización.
Dado que un hilo virtual bloqueado bloquearía el hilo del sistema operativo que ocupa en ese momento, se requiere un gran esfuerzo en tiempo de ejecución para gestionar las llamadas al sistema que provocan bloqueos. Normalmente, se utiliza un hilo de un grupo de hilos del sistema operativo disponibles para ejecutar la llamada que provoca el bloqueo del hilo virtual, de modo que el hilo del sistema operativo que se está ejecutando inicialmente no se bloquee.
La gestión de la pila de hilos virtuales requiere cuidado en el enlazador y predicciones breves de los requisitos de espacio adicional en la pila.
Implementaciones
Navegador Google Chrome
Los hilos virtuales se utilizan para serializar actividades de entrada/salida de instancia única y están disponibles para los desarrolladores que extienden el navegador. Cuando un hilo virtual se está ejecutando, puede saltar a un hilo diferente del sistema operativo. [ 15 ]
Ir
Las goroutines de Go se volvieron preventivas con Go 1.4 en 2014 y son una aplicación destacada de los hilos virtuales.
Java
Java introdujo hilos virtuales mayormente preventivos en 2023 con Java 21, con la limitación de que cualquier código que se ejecute en un hilo virtual y que utilice bloques sincronizados o llamadas nativas quedará fijado a su hilo del sistema operativo portador. [ 16 ] La limitación anterior se corrigió en Java 24. [ 17 ]
Otros usos del término
Intel [ 18 ] en 2007 se refirió a una técnica de optimización específica del compilador de Intel como hilos virtuales.
Véase también
Referencias
- ↑ Rudell, Harald (19 de marzo de 2022). "paralelismo virtual masivo" .
- ↑ baeldung (2022-01-02). "Número máximo de subprocesos por proceso en Linux | Baeldung en Linux" . www.baeldung.com . Consultado el 30 de marzo de 2022 .
- ↑ "Notas de la versión 1.14 de Go - El lenguaje de programación Go" . go.dev . Consultado el 30 de marzo de 2022 .
- ↑ Node.js. "No bloquees el bucle de eventos (ni el grupo de trabajadores)" . Node.js. Consultado el 30 de marzo de 2022 .
- ↑ Lu, Genchi (22 de julio de 2021). "El modelo de hilos de Java y la gorutina de Golang" . Medium . Consultado el 5 de abril de 2022 .
- ↑ "Principios para manejar miles de conexiones en Java usando Netty - Rendimiento de DZone" . dzone.com . Consultado el 30 de marzo de 2022 .
- ↑ "MacBook Pro de 14 pulgadas y MacBook Pro de 16 pulgadas" . Apple . Consultado el 30 de marzo de 2022 .
- ↑ "Preguntas frecuentes (FAQ) - El lenguaje de programación Go" . go.dev . Consultado el 30 de marzo de 2022 .
- ↑ "Borrador de JEP: Hilos virtuales (Vista previa)" . openjdk.java.net . Consultado el 30 de marzo de 2022 .
- ↑ Rudell, Harald (22 de marzo de 2022). "Número máximo de hilos virtuales en Go" .
- ↑ Szczukocki, Denis (18 de marzo de 2020). "Diferencia entre hilo y hilo virtual en Java | Baeldung" . www.baeldung.com . Consultado el 30 de marzo de 2022 .
- ↑ "Por qué puedes tener millones de Goroutines pero solo miles de hilos de Java" . rcoh.me. 12 de abril de 2018. Consultado el 30 de marzo de 2022 .
- ↑ "Principal - Principal - Wiki de OpenJDK" . wiki.openjdk.java.net . Consultado el 30 de marzo de 2022 .
- ↑ "El lenguaje de programación Go" . go.dev . 22 de marzo de 2022. Consultado el 30 de marzo de 2022 .
- ↑ "Hilos y tareas en Chrome" . chromium.googlesource.com . Consultado el 5 de abril de 2022 .
- ↑ "Hilos virtuales" . Centro de ayuda de Oracle . Consultado el 10 de septiembre de 2024 .
- ↑ "JEP 491: Sincronizar hilos virtuales sin fijación" . OpenJDK . Consultado el 30 de marzo de 2025 .
- ↑ "Intel Technology Journal" (PDF) .
Enlaces externos
- Paralelismo virtual masivo Programa Go que prueba los límites de los hilos virtuales
- Hilos (informática)
- Virtualización