Archiv April, 2010

Gestern wurde die lang erwartete CakePHP 1.3 als Stable veröffentlicht. Die Release Candidates hatte ich mir nicht wirklich angesehen, aber CakePHP 1.3 soll im Vergleich zu 1.2 schneller laufen, was allein ein Update schon rechtfertigt. Natürlich gibt es wieder eine ganze Menge neuer Features und die Migration Anleitung von CakePHP 1.2 sieht auch nicht besonders kompliziert aus. Mal sehen wann ich die Zeit finde das erste Projekt umzustellen.

*Update*
Ich habe gerade die ersten Projekte umgestellt. Die Migration war wirklich einfach und so habe ich es recht schnell online geschoben um ein paar Benchmarks laufen zu lassen. Leider ist die Performance so was von schlecht, das ich es ganz schnell wieder umgestellt habe… Das muss ich mir erst genauer ansehen und wenn nötig von CakePHP verabschieden. Die 1.2.6 hat schon keine berauschenden Werte geliefert, aber die 1.3.0 lag noch einmal gut 90% drunter.

Related Links

An Funktionen wie file() oder file_get_contents() habe ich mich mittlerweile so gewöhnt das ich sie überall benutze. Das funktioniert auch sehr gut wenn man nur kleine Dateien laden möchte, aber bei größeren Files kommen sie an ihre Grenzen. Das Problem ist das die Datei mit einem mal komplett in den Arbeitsspeicher geladen wird und dieser natürlich beschränkt ist. Bisher habe ich dann einfach das Memory Limit erhöht und gut war, aber bei einem 37GB Logfile ging das nicht mehr. PHP bietet dafür aber Abhilfe durch den Einsatz von Streams. Die Datei wird mit fopen zum lesen geöffnet und dann Zeile für Zeile eingelesen und bearbeitet.

So wurde aus diesem Code

$content = trim(file_get_contents($file));
$lines = explode("\n", $content);
foreach($lines AS $line)
{
	echo $line . "\n";
}

dieser hier.

$fp = fopen($file, 'r');
if($fp)
{
    while(!feof($fp))
    {
    	$line = fgets($fp);
    	echo $line . "\n";
    }
}

Das Memory Limit konnte damit auf 8MB bleiben und das Script verrichtet seine Arbeit. Neben fgets() gibt es auch noch stream_get_line() die das gleiche leistet. Der Unterschied ist das man bei stream_get_line() den Line Separator angeben kann. Schaut man sich die Kommentare auf php.net zu den beiden Befehlen an, dann scheint mal der eine, mal der andere schneller zu sein. Hier sind meine Beobachtungen dazu:

# stream_get_line()
$ time yes "This is a test line" | head -1000000 | \
php -r '$fp=fopen("php://stdin","r"); \
while($line=stream_get_line($fp,65535,"\n")) { 1; } fclose($fp);'

real    0m0.611s
user    0m0.660s
sys     0m0.084s
# fgets()
$ time yes "This is a test line" | head -1000000 | \
php -r '$fp=fopen("php://stdin","r"); \
while($line=fgets($fp,65535)) { 1; } fclose($fp);'

real    0m12.357s
user    0m4.468s
sys     0m0.288s

Scheinbar ist mein System ein stream_get_line() System. :)

Der PHP Gangsta beschreibt in seinem Blog wie man mit PHP Socket Stream Server erstellt und abfragt. Außerdem wird auf die Verwendung von Streamfiltern eingegangen. Damit ist es zum Beispiel möglich die Übertragenen Daten per gzip oder bzip2 zu komprimieren.

Witziger weise habe ich gerade zu einem ähnlichen Thema recherchiert und 5 Minuten später spuckte der RSS Feed diesen Post aus. :)

Related Links