Wie viele Versprechen kann Perl 6 halten?

8

Das ist ein bisschen glitzernder Titel, aber wenn ich mit Promises herumspielte, wollte ich sehen, wie weit ich mich strecken konnte die Idee. In diesem Programm mache ich es so, dass ich angeben kann, wie viele Versprechungen ich machen möchte.

  • Der Standardwert im Thread-Scheduler ist 16 Threads ( rakudo / ThreadPoolScheduler.pm )
  • Wenn ich mehr als diese Nummer angabe, hängt das Programm, aber ich bekomme keine Warnung (sagen wir "Zu viele Threads").
  • Wenn ich RAKUDO_MAX_THREADS einstelle, kann ich das Programm anhalten, aber irgendwann gibt es zu viel Thread-Konkurrenz, um zu laufen.

Ich habe wirklich zwei Fragen.

  • Wie würde ein Programm wissen, wie viele weitere Threads es machen kann? Das ist etwas mehr als die Anzahl der Versprechen, für das, was das wert ist.

  • Wie würde ich wissen, wie viele Threads ich erlauben sollte, auch wenn ich mehr machen kann?

Das ist Rakudo 2017.01 auf meinem kleinen Macbook Air mit 4 Kernen:

%Vor%     
brian d foy 17.04.2017, 10:41
quelle

2 Antworten

11

Es handelt sich nicht wirklich um Promise per se, sondern um den Thread Pool Scheduler. A Promise selbst ist nur ein Synchronisationskonstrukt. Das Konstrukt start macht tatsächlich zwei Dinge:

  1. Stellt eine neue $_ , $/ und $! innerhalb des Blocks
  2. sicher
  3. Ruft Promise.start mit diesem Block
  4. auf

Und Promise.start macht auch zwei Dinge:

  1. Erstellt und gibt ein Promise zurück
  2. Plant den Code im Block, der im Thread-Pool ausgeführt werden soll, und sorgt dafür, dass der erfolgreiche Abschluss den Promise behält und eine Ausnahme den Promise .
  3. unterbricht

Es ist nicht nur möglich, sondern auch relativ üblich, Promise -Objekte zu haben, die nicht vom Code im Thread-Pool unterstützt werden. Promise.in , Promise.anyof und Promise.allof Fabriken planen nicht sofort etwas, und es gibt alle Arten von Verwendungen von Promise , die Promise.new betreffen und dann später keep oder break aufrufen. So kann ich einfach und await auf 1000 Promise s:

erstellen %Vor%

Gleichermaßen ist ein Promise nicht die einzige Sache, die Code auf dem ThreadPoolScheduler einplanen kann. Die vielen Dinge, die Supply (wie Intervalle, Dateiüberwachung, asynchrone Sockets, asynchrone Prozesse) zurückgeben, planen alle ihre Callbacks auch dort. Es ist möglich, Code in den Stil "Fire-and-Forget" zu schreiben, indem Sie $*SCHEDULER.cue: { ... } ausführen (obwohl Sie sich oft um das Ergebnis oder irgendwelche Fehler kümmern, daher ist es nicht besonders häufig).

Der aktuelle Perl 6-Thread-Pool-Scheduler verfügt über eine konfigurierbare, aber erzwungene Obergrenze, die standardmäßig auf 16 Threads festgelegt ist. Wenn Sie eine Situation erstellen, in der alle 16 belegt sind, aber keine Fortschritte erzielen können und nur Fortschritte in der Arbeitswarteschlange auftreten, tritt ein Deadlock auf. Dies ist nichts Einzigartiges für Perl 6 Threadpool; Jeder gebundene Pool ist dafür anfällig (und jeder unbeschränkte Pool ist anfällig dafür, alle Ressourcen zu verbrauchen und den Prozess zum Erliegen zu bringen: -)).

Wie in einem anderen Post erwähnt, macht Perl 6.d await und react nicht blockierende Konstrukte; Dies war immer der Plan, aber es gab nicht genügend Entwicklungsressourcen, um es rechtzeitig für Perl 6.c. zu realisieren. Das Pragma use v6.d.PREVIEW bietet einen frühzeitigen Zugriff auf diese Funktion. (Auch eine faire Warnung, es ist ein Work in Progress.) Das Ergebnis davon ist, dass ein await oder react auf einem Thread, der dem Thread-Pool gehört, die Ausführung des geplanten Codes (für diejenigen, die neugierig sind) pausiert eine Fortsetzung) und und lassen Sie den Thread mit der weiteren Arbeit weitermachen. Die Wiederaufnahme des Codes wird geplant, wenn die erwartete Sache abgeschlossen ist, oder der react -Block bekommt done . Beachten Sie, dass Sie sich vor und nach dem await oder react in 6.d.in einem anderen Betriebssystem-Thread befinden können. (Die meisten Perl 6-Benutzer müssen sich nicht darum kümmern. Dies ist hauptsächlich für diejenigen relevant, die Bindungen zu C-Bibliotheken schreiben oder über System-y-Sachen. Und eine gute C-Bibliotheksbindung macht es so, dass Benutzer der Bindung nicht haben zu kümmern.)

Die bevorstehende 6.d-Änderung beseitigt nicht die Möglichkeit, den Thread-Pool zu erschöpfen, aber es wird bedeuten, dass eine Reihe von Möglichkeiten, die Sie in 6.c tun können, nicht mehr von Belang sind (rekursive Eroberung zu schreiben) / Teile Dinge, die await die Ergebnisse der geteilten Teile, oder Tausende von aktiven reagieren Blöcke gestartet mit start react { ... } ).

Mit Blick auf die Zukunft wird der Thread-Pool-Scheduler selbst intelligenter werden. Was folgt ist Spekulation, obwohl ich wahrscheinlich derjenige sein werde, der die Änderungen implementiert, ist es wahrscheinlich die beste Spekulation im Angebot. :-) Der Thread-Pool beginnt nach dem Fortschritt und verwendet ihn, um die Poolgröße dynamisch anzupassen. Dazu gehört, dass keine Fortschritte gemacht werden, und in Verbindung mit der Beobachtung, dass die Arbeitswarteschlangen Elemente enthalten, Threads, um den Deadlock zu versuchen und zu beheben - auf Kosten des Speicher-Overheads von hinzugefügten Threads. Heute tendiert der Thread-Pool konservativ dazu, bis zu seiner maximalen Größe aufzutauchen, auch wenn dies keine besonders optimale Wahl ist; sehr wahrscheinlich wird eine Art Hill-Climbing-Algorithmus verwendet, um zu versuchen, sich auf eine optimale Zahl zu konzentrieren. Sobald dies geschehen ist, kann der Standardwert von max_threads wesentlich erhöht werden, so dass mehr Programme - auf Kosten von einem Haufen Speicheraufwand - fertiggestellt werden können, aber die meisten werden nur mit einer Handvoll Threads ausgeführt.

    
Jonathan Worthington 20.04.2017 21:39
quelle
6

Schnellkorrektur, fügen Sie use v6.d.PREVIEW; in der ersten Zeile hinzu.
Dies behebt eine Reihe von Thread-Erschöpfungsproblemen.

Ich habe ein paar andere Änderungen wie $*SCHEDULER.max_threads hinzugefügt und die Promise "id" hinzugefügt, so dass es leicht zu sehen ist, dass die Thread-ID nicht unbedingt mit einer gegebenen Promise übereinstimmt.

%Vor% %Vor%     
Brad Gilbert 17.04.2017 13:14
quelle

Tags und Links