Sobes.tech
Middle

¿Qué es el tiempo de ejecución (runtime) y cómo funciona el planificador (scheduler)?

sobes.tech AI

Respuesta de la IA

El tiempo de ejecución (runtime) en Go es el entorno en el que se ejecutan los programas Go. Incluye:

  • Gestión de memoria: El recolector de basura gestiona automáticamente la asignación y liberación de memoria.
  • Planificador (scheduler): Gestiona la ejecución de goroutines en los hilos del sistema operativo.
  • Llamadas al sistema: Proporciona una interfaz para interactuar con el sistema operativo.
  • Primitivas de sincronización: Canales, mutexes y otros mecanismos para coordinar goroutines.

El planificador de Go implementa el modelo M:N (muchas goroutines en muchos hilos del sistema operativo). Sus componentes principales:

  • G (Goroutine): Un hilo ligero de ejecución, básicamente una abstracción sobre una función.
  • M (Machine): Un hilo del sistema operativo en el que se ejecutan programas Go.
  • P (Processor): Un procesador lógico asociado a un hilo del sistema operativo. Mantiene una cola local runnable de goroutines.

Principio de funcionamiento del planificador:

  1. Las goroutines (G) se crean y se añaden a una cola global o local runnable.
  2. Los hilos del sistema operativo (M) se asocian con procesadores lógicos (P). La cantidad de P por defecto es igual al número de núcleos CPU (GOMAXPROCS).
  3. P toma una goroutine de su cola local. Si la cola local está vacía, P intenta "robar" (steal) goroutines de la cola de otro P o de la cola global.
  4. M ejecuta la goroutine.
  5. Cuando una goroutine se bloquea (por ejemplo, al leer de un canal sin datos o al realizar una llamada al sistema), M se desacopla de P, y P queda disponible para ejecutar otra goroutine. La goroutine bloqueada se pone en espera. Cuando se elimina el bloqueo, la goroutine vuelve a estar runnable y se vuelve a poner en la cola.
  6. Si M se bloquea en una llamada al sistema, no retiene a P. Se puede crear un nuevo M o usar uno existente para que P pueda continuar ejecutando otras goroutines.

Este enfoque permite utilizar eficientemente los recursos del procesador y escalar fácilmente las tareas paralelas, ocultando la complejidad de la gestión de hilos del sistema operativo del desarrollador.

// Ejemplo de creación de una goroutine
func myFunc() {
	// Código de la goroutine
}

func main() {
	go myFunc() // Inicio de la goroutine
	// El programa principal continúa ejecutándose en paralelo
}