Auch wenn es auf den ersten Blick nicht ganz offensichtlich ist, kann man in PHP Prozesse parallelisieren.

Möglich macht dies die PHP-Funktion “popen“, die einen neuen Prozesszeiger öffnet.

Anwendungsbereiche für die Parallelisierung

Weshalb kann es aber sinnvoll sein PHP mehrere Dinge gleichzeitig erledigen zu lassen, da ja nicht zusätzliche Prozessor-Resourcen und damit höhere Geschwindigkeit zur Verfügung stehen?

Auf vielen modernen Rechnern stehen inzwischen Mehrfachkerne zur Verfügung. Da ein einzelner Prozess gleichzeitig nur einem Kern ausgeführt werden kann, wird somit die volle Leistung des Systems nicht ausgereizt. Das Betriebssystem muss also in der Lage sein die Prozesse auf die verschiedenen Kerne zu verteilen. Wenn ein laufender PHP-Prozess einen weiteren startet, dann kann dieser auf einem anderen Kern laufen, was eine echte parallele Abarbeitung zur Folge hat.

Die größten Leistungszuwächse können aber immer dann entstehen, wenn die eigentliche Arbeit nicht auf dem Host ablaufen soll. Beispiele dafür sind Webservices oder auch simple HTTP-Anfragen (auch wenn man diese via “curl” anders parallelisieren kann). Voraussetzung dafür ist, dass es immer mehrere Funktionen oder Abfragen auf möglichst verschiedenen Hosts gibt. Außerdem dürfen die Funktionen oder Abfragen nicht nicht voneinander abhängig sein.

Ein Beispiel für eine solche Aufgabenstellung kann eine Meta-Suchmaschine sein. Also eine diesem Fall ein Skript, dass Suchergebnisse von verschiedenen Suchmaschinen gleichzeitig abfragt und das Ergebnis zusammenfasst.

Vorraussetzungen für die Parallelisierung in PHP

Auf dem Server auf dem das Skript ausgeführt werden soll muss eine “CLI” - PHP - Version installiert haben.

Die Rechte müssen so gesetzt sein, dass sowohl PHP - CLI als auch das Skript selbst von PHP ausgeführt werden kann.

Der Abfragende Quellcode und der Initiator müssen in unterschiedlichen Skripten liegen.

Beispielimplementation einer Mini Meta-Suchmachine

Das Skript, dass die Parallelisierung vornimmt öffnet mittels der “popen” Funktion so viele Prozesszeiger zum “Arbeitsskript” wie simultane Prozesse ablaufen sollen. Danach werden die Ergebnisse dieser Skript ausgelesen und weiterverarbeitet. Sollte ein Prozess länger dauern als die anderen, so wird beim Auslesen so lange gewartet, bis er fertig ist. Da alle anderen Prozesse dann bereits fertig sind, werden nur noch die Ergebnisse ausgelesen, so dass der Gesamtprozess effektiv nur so lange dauert wie die langsamste Anfrage.
Als Ergebnis liegt nun Array mit den URL’s der Suchergebnisse gruppiert nach Suchmaschinen vor, das entsprechend weiterverarbeitet werden kann.

<?
 
$searchkey = 'guxx';                                            // Suchwort
$pathtocli = '/usr/bin/php';                                    // Pfad zu CLI Version von PHP
$pathtoscript = "/pfad/zum/skript/";               // Pfad zum auszuführenden Skript
 
// Array mit den URL's der Suchabfragen
$engines = array('http://www.google.de/search?hl=de&btnG=Google-Suche&meta=&q=',
                 'http://de.search.yahoo.com/search?fr=yfp-t-501&ei=UTF-8&rd=r1&p=',
                 'http://search.live.com/results.aspx?go=Suche&mkt=de-de&scope=&FORM=LIVSOP&q=');
 
// Für jede URL einen Prozess zum Zielskript öffnen
foreach ($engines as $key => $engine)
{
        $fh[$key] = popen("$pathtocli $pathtoscript \"$engine$searchkey\"", 'r' );
}
 
// Ergebnisse auslesen
foreach ($fh as $key => $handle)
{
        $result = "";
        while (!feof($handle))
        {
                $result .= fgets($handle);
        }
        $rar[$key] = explode("\n", $result);
}
 
print_r($rar);
 
?>

Das “Arbeisskript” ist für die eigentliche Anfrage an die Suchmaschinen zuständig und übernimmt in diesem Fall auch die Auswertung der Ergebnisse.

<?
 
// Abfrage mit dem CLI Argument ausführen
$result = @file_get_contents($argv[1]);
 
$pattern[] = "/<h2\ class=r><a\ href=\"(http:\/\/.*?)\"\ class=l/";     // Pattern für Google Ergebnisse
$pattern[] = "/class=yschttl href=\"(.*?)\"/";                          // Pattern für Yahoo Ergebnisse
$pattern[] = "/<h3><a\ href=\"(.*?)\"\ gping=/";                        // Pattern für die Live-Suche
 
// die Pattern auf das Ergebnis anwenden und "Newline" getrennt ausgeben
foreach ($pattern as $pkey => $spattern)
{
        if (preg_match_all($spattern, $result, $matches))
        {
                if (count($matches[1]) > 0)
                {
                        foreach($matches[1] as $key => $url)
                        {
                                echo("$url\n");
                        }
                }
        }
}
?>
These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Technorati
  • MisterWong
  • del.icio.us
  • Digg
  • BlinkList
  • Furl