Parallel in PHP

Concurrency mit Swoole: So programmiert man nebenläufig in PHP

Concurrency mit Swoole: So programmiert man nebenläufig in PHP

Parallel in PHP

Concurrency mit Swoole: So programmiert man nebenläufig in PHP


Die meisten Programmiersprachen enthalten Konstrukte für nebenläufiges Programmieren. In PHP schickt sich das Projekt Swoole an, Concurrency nach dem Vorbild von Google Go einzuführen. Andrei Avram erklärt, wie das geht!

Swoole ist ein CLI Server und wurde als PHP-Extension in C geschrieben. Der Server verarbeitet HTTP, TCP und Socket-Server und bietet einige wirklich interessante Funktionen. Die Features, die ich getestet habe  – und von denen ich ziemlich begeistert bin -, beschäftigen sich mit Concurrency.

Concurrency in PHP  mit Swoole

Die Entwickler von Swoole haben ein Concurrency-Modell implementiert, das sehr an das von Go erinnert. Das Modell verwendet Co-Routinen und Kanäle für die prozessübergreifende Kommunikation. Es verfügt über eine Memory Map, atomare Objekte, Locks, Puffer, Timer und vieles andere mehr.

Ausprobiert habe ich Swoole in der Version 2.2, die ich über das PECL-Repository installiert habe. Erst kürzlich ist indes Version 4.0.0 erschienen. Meine Begeisterung darüber wurde allerdings ein wenig dadurch gedämpft, dass mit Swoole 4.0.0 ein ziemlich gravierender Bug ausgeliefert wurde. Aber das Swoole-Team war schnell dabei, den Fehler zu beheben (eine neue Version war zum Zeitpunkt des Schreibens dieses Beitrags allerdings noch nicht verfügbar – den Bugfix kann man dennoch durch das Kompilieren vom Master Branch erhalten).

Schauen wir uns ein kleines Beispiel an, wie Concurrency mittels Routinen auf einem Kanal funktioniert.

Concurrency in PHP  mit Swoole

Wir beginnen mit der traditionellen Art, über eine Reihe von Daten zu iterieren und eine Validierungsfunktion aufzurufen. Wenn die Funktion slowValidationFunction eine Sekunde benötigt, dauert es für 60 Elemente eine Minute, um den gesamten Prozess zu validieren.

$items = ["item1", "item2", "item3" ...];
$size = count($items);
$chan = new chan($size);
 
$result = [];
foreach ($items as $item) {
    $valid = slowValidationFunction($item);
    $result[$item] = $valid;
}
 
print_r($result);

Beim parallelen Aufruf der slowValidationFunction dauert alles insgesamt eine Sekunde. Die Begrenzung für diese Methode liegt in den Hardware-Ressourcen (RAM und in einigen Fällen die CPU).

$items = ["item1", "item2", "item3" ...];
$size = count($items);
$chan = new chan($size);
 
foreach ($items as $item) {
    go(function () use($item, $chan) {
        $valid = slowValidationFunction($item);
        $chan->push([$item => $valid]);
    });
}
 
$result = [];
for ($i = $size; $i > 0; $i--) {
    $result = array_merge($result, $chan->pop());
}

Wer Go kennt, dürfte die Codebeispiele auf Anhieb verstehen. Die Idee dabei ist die folgende:

  • Man erstellt einen Kanal $chan, der eine bestimmte Anzahl $size von Elementen enthält. Das Besondere an diesem Kanal ist, dass er sicher zwischen verschiedenen PHP-Prozessen verwendet werden kann. Anders als sonst wird nicht der gesamte Code in einem Prozess aufgeführt. Stattdessen haben wir einen Hauptprozess und eine Anzahl $size von zusätzlichen Prozessen – einen für jeden Aufruf von slowValidationfunction() –, die gleichzeitig ausgeführt werden.
  • Verwendet man die Swoole-Funktion go mit einer Funktion als Argument, startet man $size Prozesse mit der Validierung der Elemente. Anschließend leitet man das Ergebnis jeder Validierung in den Channel.
  • Zu guter Letzt lesen wir die gesamten Ergebnisse vom Kanal.

Mit Co-Routinen können allerdings subtile Probleme entstehen, die manchmal schwer manuell zu debuggen sind. Deshalb arbeiten die Entwickler derzeit an einem Debugging-Tool für Co-Routinen. Xdebug ist an dieser Stelle wenig hilfreich.

Swoole lässt sich einfach via PECL installieren:

pecl install swoole-2.2.0

Wer Swoole einmal selbst ausprobieren möchte, findet auf GitHub eine vollständige Umgebung und eine etwas umfangreichere Anwendung als die hier gezeigte. Die Dokumentation gibt’s auf der Swoole-Website sowie auf php.net.

Soweit unsere kurze Vorstellung von Swoole. Ich hoffe, Concurrency wird ein großes Thema für PHP. Aus meiner Sicht hat Swoole das Potenzial, PHP auf eine neue Ebene zu heben!

Dieser Beitrag ist im englischen Original erschienen auf Andrei Avrams Blog: Concurrency in PHP with Swoole

Andrei Avram ist Senior Backend-Entwickler bei Zenitech. Sein Fokus liegt auf skalierbaren und wartbaren Anwendungen, vor allem auf Basis von REST-Webservices. Seine Leidenschaft sind Design Patterns, SOLID-Prinzipien, DRY und Coding Standards (PSR).


Weitere Artikel zu diesem Thema