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