Middle
Cos'è il tempo di esecuzione (runtime) e come funziona il pianificatore (scheduler)?
sobes.tech AI
Risposta dell'AI
Il runtime in Go è l'ambiente in cui vengono eseguiti i programmi Go. Include:
- Gestione della memoria: Il garbage collector gestisce automaticamente l'allocazione e la liberazione della memoria.
- Scheduler: Gestisce l'esecuzione delle goroutine sui thread del sistema operativo.
- Chiamate di sistema: Fornisce un'interfaccia per interagire con il sistema operativo.
- Primitive di sincronizzazione: Canali, mutex e altri meccanismi per coordinare le goroutine.
Il scheduler di Go implementa il modello M:N (molte goroutine su molti thread del sistema operativo). I suoi componenti principali:
- G (Goroutine): Un thread leggero di esecuzione, fondamentalmente un'astrazione di una funzione.
- M (Machine): Un thread del sistema operativo su cui vengono eseguiti i programmi Go.
- P (Processor): Un processore logico associato a un thread del sistema operativo. Tiene una coda locale
runnabledi goroutine.
Principio di funzionamento dello scheduler:
- Le goroutine (G) vengono create e aggiunte a una coda globale o locale
runnable. - I thread del sistema operativo (M) sono associati a processori logici (P). La quantità di P di default è uguale al numero di core CPU (
GOMAXPROCS). - P prende una goroutine dalla sua coda locale. Se la coda locale è vuota, P tenta di "rubare" (steal) goroutine dalla coda di un altro P o dalla coda globale.
- M esegue la goroutine.
- Quando una goroutine si blocca (ad esempio, durante la lettura da un canale senza dati o durante una chiamata di sistema), M si disassocia da P, e P diventa disponibile per eseguire un'altra goroutine. La goroutine bloccata viene messa in attesa. Quando il blocco viene rimosso, la goroutine torna a essere
runnablee viene rimessa in coda. - Se M si blocca in una chiamata di sistema, non mantiene P. Può essere creato un nuovo M o può essere usato uno esistente, affinché P possa continuare a eseguire altre goroutine.
Questo approccio permette di utilizzare efficacemente le risorse del processore e di scalare facilmente le attività parallele, nascondendo la complessità della gestione dei thread del sistema operativo allo sviluppatore.
// Esempio di creazione di una goroutine
func myFunc() {
// Codice della goroutine
}
func main() {
go myFunc() // Avvio della goroutine
// Il programma principale continua l'esecuzione in parallelo
}