2009-12-31 13 views
8

Sto solo imparando, e mi piace molto, il pattern degli attori. In questo momento sto usando Scala, ma mi interessa lo stile architettonico in generale, come è usato in Scala, Erlang, Groovy, ecc.Ha senso utilizzare un pool di attori?

Il caso a cui sto pensando è dove devo fare le cose contemporaneamente, come, diciamo "eseguire un lavoro".

Con il threading, vorrei creare un pool di thread e una coda di blocco e fare in modo che ogni thread esegua il polling della coda di blocco ed elabori i lavori mentre entravano e uscivano dalla coda.

Con gli attori, qual è il modo migliore per gestirlo? Ha senso creare un gruppo di attori e in qualche modo inviare loro messaggi contenenti o lavori? Forse con un attore "coordinatore"?

Nota: Un aspetto del caso che ho dimenticato di dire era: che cosa se voglio limitare il numero di posti di lavoro la mia app elaborerà contemporaneamente? Forse con un settaggio di configurazione? Stavo pensando che un pool potrebbe renderlo facile farlo.

Grazie!

+1

Sì, ha senso limitare il numero di attori che lavorano su un elenco di attività. Almeno Erlang ti dà abbastanza concorrenza da poter esaurire la maggior parte delle risorse di sistema generando abbastanza processi che li utilizzano. – Christian

+0

Ho cercato di riformulare questa domanda in un modo più focalizzato, specifico e concreto qui: http://stackoverflow.com/questions/2312195/how-to-limit-concurrency-when-using-actors-in-scala –

risposta

4

A volte, ha senso limitare il numero di processi di lavoro che si stanno utilizzando contemporaneamente in un elenco di attività di grandi dimensioni, poiché l'attività in cui il processo viene generato per completare comporta allocazioni di risorse. Per lo meno i processi consumano memoria, ma possono anche tenere aperti file e/o socket che tendono ad essere limitati a solo migliaia e che falliscono miseramente e imprevedibili una volta esauriti.

Per avere un pull-driven piscina compito , si può generare N processi legati che chiedono per un compito, e da una parte di loro una funzione che possono spawn_monitor. Non appena il processo monitorato è terminato, tornano per il prossimo compito. Le esigenze specifiche guidano i dettagli, ma questo è lo schema di un approccio.

Il motivo per cui ogni attività genera un nuovo processo è che i processi hanno uno stato ed è bello iniziare una lista pulita. È una regolazione fine comune per impostare le dimensioni min-heap dei processi aggiustate per ridurre al minimo il numero di GC necessari durante la sua vita. È anche una garbage collection molto efficiente per liberare tutta la memoria per un processo e avviarne una nuova per l'attività successiva.

Sembra strano utilizzare il doppio del numero di processi come quello? È una sensazione che devi superare nella programmazione di Erlang.

+0

Molto interessante, grazie! Potrei contrassegnarlo come la risposta "accettata", devo riflettere su questo. –

5

Un pool è un meccanismo che si utilizza quando il costo di creazione e demolizione di una risorsa è elevato. In Erlang questo non è il caso, quindi non si dovrebbe mantenere una piscina.

Dovresti generare i processi quando ne hai bisogno e distruggerli quando hai finito con loro.

+0

Grazie, ma cosa succede se voglio limitare il numero di lavori che la mia app elaborerà in modo concorrente? Forse con un settaggio di configurazione? Stavo pensando che una piscina rende facile farlo. –

+3

@Avi: Penso che sia necessario fare una distinzione qui. Un "pool" di solito si riferisce (almeno per me) a preservare effettivamente gli attori/processi e riutilizzarli. In Erlang non hai bisogno di farlo, puoi semplicemente buttarli via e crearne di nuovi. Naturalmente è possibile implementare un "contatore globale" (nella forma di un processo server, in una tabella ets, ecc.), Che è possibile eseguire il polling prima di generare nuovamente un altro processo. Infatti, per ottenere il controllo del carico è necessario un dispositivo come questo ... – Zed

+0

@Zed: buoni punti, grazie. Forse avrei dovuto chiedere "Qual è un buon modo per limitare la concorrenza con gli attori?" –

2

Non esiste un modo migliore per tutti i casi. La decisione dipende dal numero, dalla durata, dall'arrivo e dall'ora di completamento richiesta dei lavori.

La differenza più ovvia tra la semplice distribuzione di attori e l'utilizzo di pool è che nel primo caso i lavori saranno terminati quasi contemporaneamente, mentre in quest'ultimo caso i tempi di completamento saranno distribuiti nel tempo. Il tempo medio di completamento sarà lo stesso però.

Il vantaggio di utilizzare gli attori è la semplicità della codifica, in quanto non richiede alcuna gestione aggiuntiva. Il compromesso è che i tuoi attori competeranno per i tuoi core CPU.Non sarà possibile avere più processi paralleli rispetto ai core CPU (o HT, a prescindere), indipendentemente dal paradigma di programmazione che si utilizza.

Ad esempio, immagina di dover eseguire 100'000 lavori, ognuno dei quali richiede un minuto, e i risultati sono dovuti il ​​mese prossimo. Hai quattro core. Creeresti 100'000 attori che si contenderanno ciascuno le risorse per un mese, o metteresti in coda i tuoi lavori e ne eseguirai quattro alla volta?

Come controesempio, immaginare un server Web in esecuzione sulla stessa macchina. Se hai cinque richieste, preferiresti servire quattro utenti in T time e uno in 2T, o servire tutti e cinque in 1.2T?

Problemi correlati