Le piscine goroutine go-lang sono solo fili verdi?


47

Il commentatore qui offre le seguenti critiche ai fili verdi:

Inizialmente sono stato venduto sul modello N: M come mezzo per avere la programmazione guidata dagli eventi senza l'inferno di callback. Puoi scrivere codice che assomiglia a un vecchio codice procedurale, ma sotto c'è una magia che utilizza il cambio di attività dello spazio utente ogni volta che qualcosa si blocca. Suona alla grande. Il problema è che finiamo per risolvere la complessità con più complessità. swapcontext () e la famiglia sono piuttosto stretti in avanti, la complessità proviene da altri luoghi non intenzionali.

All'improvviso sei costretto a scrivere uno scheduler dello spazio utente e indovinare cosa è davvero difficile scrivere uno scheduler che farà un lavoro migliore rispetto ai programmi di Linux che hanno anni di sforzi. Ora vuoi che il tuo programma gestisca N thread verdi su M thread fisici, quindi devi preoccuparti della sincronizzazione. La sincronizzazione porta problemi di prestazioni in modo da iniziare ora che sei in una nuova tana di coniglio senza blocco. Costruire uno scheduler altamente simultaneo corretto non è un compito facile.

Un'altra critica è qui :

Un singolo processo che simula più thread ha molti problemi. Uno di questi è che tutti i fili falsi si bloccano su qualsiasi errore di pagina.

La mia domanda è - si -go Lang goroutines di (per un pool di default) a soli fili verdi? In tal caso, affrontano le critiche sopra?

Risposte:


67

Sono solo un utente Go occasionale, quindi prendi quanto segue con un pizzico di sale.

Wikipedia definisce i thread verdi come "thread pianificati da una macchina virtuale (VM) anziché nativamente dal sistema operativo sottostante". I thread verdi emulano ambienti multithread senza fare affidamento su alcuna capacità del sistema operativo nativo e sono gestiti nello spazio utente anziché nello spazio del kernel, consentendo loro di lavorare in ambienti che non supportano il thread nativo.

Go (o più esattamente le due implementazioni esistenti) è un linguaggio che produce solo codice nativo: non utilizza una macchina virtuale. Inoltre, lo scheduler nelle attuali implementazioni di runtime si basa su thread a livello di sistema operativo (anche quando GOMAXPROCS = 1). Quindi penso che parlare di fili verdi per il modello Go sia un po 'offensivo.

Go people ha coniato il termine goroutine soprattutto per evitare la confusione con altri meccanismi di concorrenza (come coroutine o fili o processi leggeri).

Ovviamente, Go supporta un modello di threading M: N, ma sembra molto più vicino al modello di processo Erlang che al modello di thread verde Java.

Ecco alcuni vantaggi del modello Go rispetto ai thread verdi (come implementato nei primi JVM):

  • Più core o CPU possono essere utilizzati in modo efficace, in modo trasparente per lo sviluppatore. Con Go, lo sviluppatore dovrebbe occuparsi della concorrenza. Il runtime Go si occuperà del parallelismo. Le implementazioni dei thread verdi Java non si sono ridimensionate su più core o CPU.

  • Le chiamate di sistema e C non sono bloccanti per lo scheduler (tutte le chiamate di sistema, non solo quelle che supportano gli I / O multiplexati nei loop di eventi). Le implementazioni di thread verdi potrebbero bloccare l'intero processo quando è stata effettuata una chiamata di sistema di blocco.

  • Pile copiate o segmentate. In Go, non è necessario fornire una dimensione massima dello stack per la goroutine. Lo stack cresce in modo incrementale secondo necessità. Una conseguenza è che una goroutine non richiede molta memoria (4KB-8KB), quindi un numero enorme di essi può essere generato felicemente. L'uso goroutine può quindi essere pervasivo.

Ora, per affrontare le critiche:

  • Con Go non è necessario scrivere uno scheduler dello spazio utente: è già fornito con il runtime. È un software complesso, ma è il problema degli sviluppatori Go, non degli utenti Go. Il suo utilizzo è trasparente per gli utenti Go. Tra gli sviluppatori Go, Dmitri Vyukov è un esperto di programmazione lockfree / waitfree e sembra essere particolarmente interessato ad affrontare eventuali problemi di prestazioni dello scheduler. L'attuale implementazione dello scheduler non è perfetta, ma migliorerà.

  • La sincronizzazione porta problemi di prestazioni e complessità: questo è parzialmente vero anche con Go. Ma nota che il modello Go cerca di promuovere l'uso dei canali e una chiara decomposizione del programma in goroutine simultanee per limitare la complessità della sincronizzazione (cioè condividere i dati comunicando, invece di condividere la memoria per comunicare). A proposito, l'implementazione Go di riferimento fornisce una serie di strumenti per affrontare i problemi di prestazioni e concorrenza, come un profiler e un rilevatore di gare .

  • Per quanto riguarda l'errore di pagina e "falsificazione di più thread", si noti che Go può programmare goroutine su più thread di sistema. Quando un thread viene bloccato per qualsiasi motivo (errore di pagina, blocco delle chiamate di sistema), non impedisce agli altri thread di continuare a pianificare ed eseguire altre goroutine. Ora, è vero che un errore di pagina bloccherà il thread del sistema operativo, con tutte le goroutine che dovrebbero essere programmate su questo thread. Tuttavia, in pratica, la memoria dell'heap Go non dovrebbe essere sostituita. Questo sarebbe lo stesso in Java: i linguaggi raccolti in modo errato non soddisfano molto bene la memoria virtuale. Se il tuo programma deve gestire l'errore di pagina in modo grazioso, probabilmente perché deve gestire un po 'di memoria off-heap. In quel caso,

Quindi, IMO, le goroutine non sono fili verdi e il linguaggio Go e l'attuale implementazione affrontano principalmente queste critiche.


1
Una risposta eccellente e dettagliata alla domanda :)
Tuxdude,

1
Adoro questa risposta, ma hai qualche riferimento a come / quando vengono creati i thread del sistema operativo?
Lars,

1
Uno dei maggiori svantaggi di Go Language è che crea un thread del kernel per ogni chiamata di sistema bloccante!
user1870400

8
Si noti che l'articolo "thread verde" su Wikipedia è stato modificato per indicare "thread pianificati da una libreria di runtime o macchina virtuale (VM)"; il che significa che secondo quella definizione la tua risposta non sarebbe più corretta, poiché il runtime Go fa la pianificazione / gestione. Penso che sia più utile definire thread verdi come thread dello spazio utente che contrastano i thread del sistema operativo. E poi, sì, le goroutine sono sicuramente fili verdi.
mknecht,

1
2 ° che @mknecht. Non si tratta della VM, si tratta di runtime. E Go ha sicuramente un tempo di esecuzione. (che gestisce il modello di threading e la garbage collection).
Tim Harper,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.