Facebook
Twitter
Google+
Kommentare
0

cURL vs. Fopen vs. ZF

In Moment ist ein sehr gefährlicher Infekt in der PHP-Szene namens “ PhpBenchmarkItis” in Umlauf. Wenn es erwischt hat, derjenige ist gezwungen Dinge in PHP miteinander auf Leistung und Schnelligkeit gegeneinander zu prüfen. Mich hat die “ PhpBenchmarkItis” nun auch erwischt. Ich musste unbedingt erfahren welche Methode von PHP und ZF eine schnellere Verbindung zu einem Server aufbaut und dessen Antwort bzw. Ergebnis ausliefert. Hintergrund des Ganzen ist, eine Klasse zu erstellen die auf dem schnellsten Wege verschiedene RSS-Feeds auslesen und ausliefern kann.

Die Testumgebung
Server = Debian 5.0.4
Processors = Intel(R) Xeon(R) CPU E5335 @ 2.00GHz
PHP Version = 5.3.3-0.dotdeb.1
allow_url_fopen = On
cURL Version = 7.18.2
ZendFramework Version = 1.10.0

Das Test-Scenario
Als Testumgebung dient PHPUnit, da jeder Test isoliert ausgeführt werden kann. Jede Methode ruft den RSS-Feed (http://krsteski.de/feed/rss) auf dieses Blog 50-mal auf und liefert ebenso 50-mal den Inhalt zurück. Gut, dieser Blog ist eine WordPress Instanz und braucht etwas zu antworten, jedoch alles in akzeptablen Zeitrahmen. Getestet werden hier: file_get_contents, fopen, Zend_Http_Client, Zend_Feed_Reader und cURL.

< ?php
class Feed_PhpBenchmarkItis extends PHPUnit_Framework_TestCase
{
    const LOOP = 50;
    const FEED = 'http://krsteski.de/feed/rss';

    public function testZendFeed()
    {
        $beginn = microtime(true);

        $i = 0;
        while($i < self::LOOP)
        {
            $feed = Zend_Feed_Reader::importFile(self::FEED);
            $feed->getFeedLink();

            ++$i;
        }

        $dauer = sprintf('%.3f', microtime(true) - $beginn);

        echo self::LOOP." ZENDFEED Anfragen in: ".
                $dauer." Sek. durchschnittlich ".
                ($dauer / self::LOOP)." Sek. pro Anfrage".PHP_EOL;
    }

    public function testFILE_GET_CONTENTS()
    {
        $beginn = microtime(true);

        $i = 0;
        while($i < self::LOOP)
        {
            $contents = file_get_contents(self::FEED);

            ++$i;
        }

        $dauer = sprintf('%.3f', microtime(true) - $beginn);

        echo self::LOOP." FILE_GET_CONTENTS Anfragen in: ".
                $dauer." Sek. durchschnittlich ".
                ($dauer / self::LOOP)." Sek. pro Anfrage".PHP_EOL;

    }

    public function testFOPEN ()
    {
        $beginn = microtime(true);

        $i = 0;
        while($i < self::LOOP)
        {
            $handle = fopen(self::FEED, "r");
            $contents = stream_get_contents($handle, -1);
            fclose($handle);

            ++$i;
        }

        $dauer = sprintf('%.3f', microtime(true) - $beginn);

        echo self::LOOP." FOPEN Anfragen in: ".
                $dauer." Sek. durchschnittlich ".
                ($dauer / self::LOOP)." Sek. pro Anfrage".PHP_EOL;

    }

    public function testCURL()
    {
        $beginn = microtime(true);

        $i = 0;
        while($i < self::LOOP)
        {
            $handle = curl_init(self::FEED);
            curl_setopt($handle, CURLOPT_HEADER, false);
            curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
            $contents = curl_exec($handle);
            curl_close($handle);

            ++$i;
        }

        $dauer = sprintf('%.3f', microtime(true) - $beginn);

        echo self::LOOP." CURL Anfragen in: ".
            $dauer." Sek. durchschnittlich ".
            ($dauer / self::LOOP)." Sek. pro Anfrage".PHP_EOL;
    }

    public function testZendHttpClient()
    {
        $beginn = microtime(true);

        $i = 0;
        while($i < self::LOOP)
        {
            $urlClient = new Zend_Http_Client(self::FEED);
            $contents = $urlClient->request()->getRawBody();

            ++$i;
        }

        $dauer = sprintf('%.3f', microtime(true) - $beginn);

        echo self::LOOP." ZEND_HTTP_CLIENT Anfragen in: ".
            $dauer." Sek. durchschnittlich ".
            ($dauer / self::LOOP)." Sek. pro Anfrage".PHP_EOL;
    }
}

Das Testergebnis

50 ZENDFEED Anfragen in: 4.007 Sek. durchschnittlich 0.08014 Sek. pro Anfrage
50 FILE_GET_CONTENTS Anfragen in: 4.016 Sek. durchschnittlich 0.08032 Sek. pro Anfrage
50 FOPEN Anfragen in: 6.295 Sek. durchschnittlich 0.1259 Sek. pro Anfrage
50 CURL Anfragen in: 3.564 Sek. durchschnittlich 0.07128 Sek. pro Anfrage
50 ZEND_HTTP_CLIENT Anfragen in: 3.999 Sek. durchschnittlich 0.07998 Sek. pro Anfrage
Time: 23 seconds, Memory: 9.75Mb

Wie erwartet ist hier der Aufruf mit cURL schneller. Bei cURL habe ich jedoch das Problem, dass ich hier nicht genau weiß ob es sich um ein valides RSS-Feed handelt. Zudem muss ich das Ergebnis das cURL zurück liefert, irgendwie parsen um es weiter verarbeiten zu können. Diese Logik muss also zusätzlich implementiert werden. Ich habe mich für Zend_Feed_Reader entschieden und verzichte gerne auf bisschen Zeit und bekomme dafür mehr Sicherheit. Zudem der Zend_Feed_Reader kann das RSS-Feed validieren, löst entsprechenden Exceptions falls es irgendwelche Probleme mit dem RSS-Feed gibt und liefert das Ergebnis als eine DOMDocument Instanz zurück. Und das ist ja spitze! Anhand der DOMDocument Instanz kann ich nun ganz bequem über den Datenbestand iterieren.

Über den Autor

Gjero Krsteski

Link erfolgreich vorgeschlagen.

Vielen Dank, dass du einen Link vorgeschlagen hast. Wir werden ihn sobald wie möglich prüfen. Schließen