Andreas Korthaus: PHP in PERL umschreiben

Beitrag lesen

Hi!

Perl ist gar nicht so schwer ("Programming Perl" - Larry Wall, O'Reilly).

das nicht, aber PHP ist wunderbar für sowas geeignet ;-)

Vielleicht programmiert ihr auch einfach ziemlich ... dämlich.

vermutlich..., der Satz:

Die Logfile des Webalizers ist recht simple aufgebaut und kann daher durch die schnellen explodes (sofern mir bekannt ist laufen diese schneller als preg_match-Abfragen) aufgesplittet werden.

legt das nahe. (btw: vermutlich meint Ihr die Logfiles des Webservers)

Ich denke ihr lest die Datei mit file() ein, oder? Dann würde die ganze Datei erst geparst und komplett inein Array gechreben, wozu dann entsprechend viel Speicher verbraucht wird.

Wenn man nicht alles gleichzeitig verarbeitet, sondern immer Stück für Stück Filter für Filter sequentiell anwendet (Datei A -> Filter -> Datei B -> Filter -> Datei C/D...  Datei C -> Filter -> Datei C2, Datei D-> Filter -> Datei D2) , dann könnte es möglicherweise mit weniger Speicheraufwand und schneller gehen.

meinst Du "Datei" oder "Zeile"?

Ich würde das einlesen etwas so machen:

<?php
$file ='access_log';
$fp = fopen ($file, 'r');
do {
    $line = fgets($fp,4096);
    if (strlen($line) == 0) {
        break;
    }
    // hier die Filterfunktion
} while(true);
fclose ($fp);
?>

Das setzt allerdings voraus dass es keine leerzeilen gibt, was ja eigentlich der Normalfall ist. Zur Not kann man ja noch die strlen aufaddieren und mit der Dateigröße vergleichen. Der Sinn dahinter ist dass nicht 1 feof() Aufruf pro Zeile notwendig wird, strlen() ist da erheblich performanter.
Praktisch wäre es, die Zeile direkt mit fgetcsv() in ein Array zu lesen, nur ist das glaube ich nicht möglich da die "enclosure" Zeichen nicht durchgängig verwendet werden, ich glaube zumindest das es dann nicht geht.

Das Problem ist, dass Du die einzelnen Elemente nicht so ohne weiteres per explode() tennen kannst, denn anhand welches Trennzeichen? " " geht nicht. Das heißt dass Du Dir entweder eine  eigene spezielle Funktion hierfür schreiben musst, oder per preg_match verwenden musst.

Achte auch darauf dass Du jetzt nicht doch einen Array verwendest in den Du die geamte Logfile nach und nach reinschreibst, sondern überschreibe die Elemente, oder am besten greife direkt drauf zu, vielleicht könntest Du mit einer eigenen Funktion nur die wichtigen Eckpunkte der jeweiligen Strings innerhalb von $data merken, also in einen Array schreiben, und dann nur mit substr() drauf zugreifen.

Ich würde evtl. auch eine Referenz auf den geparsten String verwenden falls Du den kopierst oder an eine Funktion übergibts. Naja, es kommt drauf an was Du genau machst, man kann das ganze mit solchen Spielereien natürlich auch verlangsamen.

Teste einfach mal ein bisschen rum und vergleiche am Ende die Performance. Ich habe das auch mal irgendwo gemacht, und dabei kam raus das preg_match durchaus performant ist.

Viele Grüße
Andreas