2009-12-31 12 views
8

Ich lerne gerade, und wirklich mag das Schauspieler-Muster. Ich benutze Scala im Moment, aber ich bin interessiert an der Architektur im Allgemeinen, wie es in Scala, Erlang, Groovy usw. verwendet wird.Macht es Sinn, einen Pool von Akteuren zu benutzen?

Der Fall, an den ich denke, ist, wo ich Dinge tun muss gleichzeitig, wie zum Beispiel "einen Job ausführen".

Mit Threading, ich würde einen Thread-Pool und eine blockierende Warteschlange erstellen, und jeden Thread die blockierende Warteschlange abfragen und Jobs verarbeiten, wie sie in und aus der Warteschlange kamen.

Mit Schauspielern, was ist der beste Weg, damit umzugehen? Macht es Sinn, einen Pool von Akteuren zu erstellen und irgendwie Nachrichten an sie zu senden, die die Jobs enthalten? Vielleicht mit einem "Koordinator" Schauspieler?

Hinweis: Ein Aspekt des Falles, den ich war vergessen zu erwähnen: Was passiert, wenn ich die Zahl der Arbeitsplätze meine App verarbeitet gleichzeitig einschränken will? Vielleicht mit einer Konfigurationseinstellung? Ich dachte, dass ein Pool es leicht machen könnte, dies zu tun.

Danke!

+1

Ja, es ist sinnvoll, die Anzahl der Akteure auf einer Aufgabenliste zu begrenzen. Zumindest gibt Erlang Ihnen genug Nebenläufigkeit, dass Sie die meisten Systemressourcen erschöpfen können, indem Sie genügend Prozesse erzeugen, die diese nutzen. – Christian

+0

Ich habe versucht, diese Frage in einer gezielteren, konkreteren, konkreteren Weise hier umzuformulieren: http://stackoverflow.com/questions/2312195/how-to-limit-concurrency-when-using-actors-in-scala –

Antwort

4

Manchmal ist es sinnvoll, die Anzahl der Arbeitsprozesse zu begrenzen, die gleichzeitig auf einer großen Aufgabenliste ausgeführt werden, da die Aufgabe, zu deren Abschluss der Prozess ausgeführt wird, Ressourcenzuweisungen umfasst. Zumindest verbrauchen Prozesse Speicher, aber sie können auch Dateien und/oder Sockets offen halten, die dazu neigen, nur auf Tausende beschränkt zu sein und scheitern kläglich und unvorhersehbar, wenn Sie einmal ausgelaufen sind.

Um eine Pull-driven Aufgabe Pool haben, kann man N verknüpften Prozesse Laichen die für eine Aufgabe stellen, und eine Hand sie eine Funktion, die sie spawn_monitor können. Sobald der überwachte Prozess beendet ist, kommen sie für die nächste Aufgabe zurück. Spezifische Bedürfnisse treiben die Details, aber das ist der Grundriss eines Ansatzes.

Der Grund, warum ich jede Aufgabe einen neuen Prozess erstellen lassen würde, ist, dass Prozesse einen gewissen Status haben und es nett ist, eine saubere Weste zu starten. Es ist eine häufige Feinabstimmung, um die Min-Heap-Größe von Prozessen einzustellen, die angepasst werden, um die Anzahl von GCs zu minimieren, die während ihrer Lebensdauer benötigt werden. Es ist auch eine sehr effiziente Speicherbereinigung, um den gesamten Speicher für einen Prozess freizugeben und mit einem neuen für die nächste Aufgabe zu beginnen.

Fühlt es sich komisch an, die doppelte Anzahl solcher Prozesse zu verwenden? Es ist ein Gefühl, das Sie in Erlang Programmierung überwinden müssen.

+0

Sehr interessant, danke! Ich könnte dies als die "akzeptierte" Antwort bezeichnen, ich muss darüber nachdenken. –

5

Ein Pool ist ein Mechanismus, den Sie verwenden, wenn die Kosten für das Erstellen und Abbauen einer Ressource hoch sind. In Erlang ist dies nicht der Fall, also sollten Sie keinen Pool pflegen.

Sie sollten Prozesse erzeugen, wie Sie sie brauchen, und sie zerstören, wenn Sie damit fertig sind.

+0

Danke, aber was, wenn ich die Anzahl der Jobs beschränken möchte, die meine App gleichzeitig verarbeitet? Vielleicht mit einer Konfigurationseinstellung? Ich dachte, dass ein Pool es einfach macht. –

+3

@Avi: Ich denke, dass Sie hier unterscheiden müssen. Ein "Pool" bezieht sich normalerweise (zumindest für mich) darauf, die Akteure/Prozesse tatsächlich zu erhalten und sie wiederzuverwenden. In Erlang brauchst du das nicht, du kannst sie einfach wegwerfen und neue spawnen. Natürlich können Sie einen "globalen Zähler" implementieren (in Form eines Serverprozesses, in einer ETS-Tabelle usw.), den Sie abfragen können, bevor Sie einen anderen Jobprozess erstellen. In der Tat brauchen Sie eine solche Einrichtung, um eine Lastkontrolle zu erreichen ... – Zed

+0

@Zed: Gute Punkte, danke. Vielleicht hätte ich fragen sollen "Was ist ein guter Weg, die Nebenläufigkeit mit Schauspielern zu begrenzen?" –

2

Es gibt keinen besten Weg für alle Fälle. Die Entscheidung hängt von der Anzahl, Dauer, Ankunft und der erforderlichen Ausführungszeit der Aufträge ab. Der offensichtlichste Unterschied zwischen dem Laichen von Schauspielern und dem Verwenden von Pools ist, dass im ersten Fall Ihre Jobs fast gleichzeitig beendet werden, während im letzteren Fall die Bearbeitungszeiten zeitlich verteilt werden.

Die durchschnittliche Bearbeitungszeit wird jedoch gleich sein.

Der Vorteil der Verwendung von Aktoren ist die Einfachheit der Codierung, da keine zusätzliche Handhabung erforderlich ist. Der Kompromiss besteht darin, dass Ihre Schauspieler um Ihre CPU-Kerne konkurrieren.Sie werden nicht mehr parallele Jobs als CPU-Cores (oder HTs, was auch immer) haben können, egal welches Programmierparadigma Sie verwenden.

Stellen Sie sich als Beispiel vor, dass Sie 100'000 Jobs mit jeweils einer Minute ausführen müssen und die Ergebnisse im nächsten Monat fällig sind. Sie haben vier Kerne. Würden Sie 100'000 Schauspieler spawnen, die jeweils einen Monat lang über die Ressourcen konkurrieren, oder würden Sie nur Ihre Jobs in die Warteschlange stellen und vier gleichzeitig ausführen?

Stellen Sie sich als Gegenbeispiel einen Webserver vor, der auf demselben Computer ausgeführt wird. Wenn Sie fünf Anfragen haben, würden Sie es vorziehen, vier Benutzer in T-Zeit und eine in 2T zu bedienen, oder alle fünf in 1.2T-Zeit zu bedienen?

Verwandte Themen