2010-08-15 5 views
5

Ich habe ein Skript, das, wenn es gegen einen Timer gesetzt wird, progressiv langsamer wird. Es ist ziemlich einfach, da es nur eine Zeile liest, prüft, dann fügt es es der Datenbank hinzu und geht dann zur nächsten Zeile über.PHP-Skript wird immer langsamer (Datei-Reader)

Hier ist der Ausgang davon nach und nach immer schlimmer:

Record: #1,001 Memory: 1,355,360kb taking 1.84s 
Record: #1,001 Memory: 1,355,360kb taking 1.84s 
Record: #2,002 Memory: 1,355,192kb taking 2.12s 
Record: #3,003 Memory: 1,355,192kb taking 2.39s 
Record: #4,004 Memory: 1,355,192kb taking 2.65s 
Record: #5,005 Memory: 1,355,200kb taking 2.94s 
Record: #6,006 Memory: 1,355,376kb taking 3.28s 
Record: #7,007 Memory: 1,355,176kb taking 3.56s 
Record: #8,008 Memory: 1,355,408kb taking 3.81s 
Record: #9,009 Memory: 1,355,464kb taking 4.07s 
Record: #10,010 Memory: 1,355,392kb taking 4.32s 
Record: #11,011 Memory: 1,355,352kb taking 4.63s 
Record: #12,012 Memory: 1,355,376kb taking 4.90s 
Record: #13,013 Memory: 1,355,200kb taking 5.14s 
Record: #14,014 Memory: 1,355,184kb taking 5.43s 
Record: #15,015 Memory: 1,355,344kb taking 5.72s 

Die Datei ist leider um ~ 20gb so werde ich wahrscheinlich durch die Zeit tot sein das Ganze bei der Steigerungsrate gelesen wird. Der Code ist (hauptsächlich) unten, aber ich vermute, dass es etwas mit fgets() zu tun hat, aber ich bin mir nicht sicher was.

$handle = fopen ($import_file, 'r'); 

    while ($line = fgets ($handle)) 
    { 
     $data = json_decode ($line); 

     save_record ($data, $line); 
    } 

Vielen Dank im Voraus!

EDIT:

kommentierte out 'save_record ($ data, $ line);' scheint nichts zu tun.

+0

Können Sie den Code für save_record buchen? Das ist wahrscheinlich der Schlüssel – Jhong

+0

Eigentlich, wenn ich die save_record() Zeile auskommentieren, ist es immer noch genauso schlecht. – DCD

+1

Wie erhalten Sie diese Leistungsausgabe? Sie haben keine Leistungsprotokollierung in dem von Ihnen bereitgestellten Codebeispiel. Ich vermute, das Problem ist woanders. Haben Sie mehr Code, den Sie uns nicht zeigen, der relevant sein könnte? –

Antwort

0

Okay geben, ein Leistungsproblem. Offensichtlich wird etwas quadratisch, wenn es nicht, oder genauer gesagt, etwas sein sollte, das konstant sein sollte - die Zeit scheint in der Anzahl der bisher behandelten Datensätze linear zu sein. Die erste Frage ist, was der minimale Code ist, der das Problem aufweist. Ich würde gerne wissen, ob Sie das gleiche problematische Verhalten bekommen, wenn Sie alles auskommentieren, aber die Datei Zeile für Zeile lesen. Wenn ja, dann brauchen Sie eine Sprache ohne dieses Problem. (Es gibt viele.) Sowieso, sobald Sie das erwartete Zeitmerkmal sehen, addieren Sie Aussagen in eins nach dem anderen, bis Ihr Timing drunter und drüber geht, und Sie haben das Problem identifiziert.

Sie instrumentiert etwas, um die Zeiten zu bekommen. Stellen Sie sicher, dass diese kein Problem verursachen können, indem Sie sie 15000-mal alleine ausführen.

1

Manchmal ist es besser, Systembefehle zum Lesen dieser großen Dateien zu verwenden. Ich lief in etwas ähnlichem und hier ist ein kleiner Trick, den ich verwenden:

$lines = exec("wc -l $filename"); 
for($i=1; $i <= $lines; $i++) { 
    $line = exec('sed \''.$i.'!d\' '.$filename); 

    // do what you want with the record here 
} 

Ich würde das nicht mit Dateien empfehlen, die nicht vertraut werden können, aber es läuft schnell, da es einen Datensatz zu einem Zeitpunkt, zieht das System. Hoffe das hilft.

+0

+1 gute Idee, ich werde das in Zukunft berücksichtigen. – alex

0

Ich habe diese Frage beim Versuch, einen Weg für mich zu finden, schneller durch eine 96G Textdatei zu finden. Das Skript, das ich ursprünglich geschrieben habe, dauerte 15 Stunden, um 0,1% zu erreichen ...

Ich habe einige der hier vorgeschlagenen Lösungen mit stream_get_line, fgets und exec für sed ausprobiert. Ich hatte eine andere Herangehensweise, die ich mit jemand anderem teilen wollte, der auf diese Frage einging.

Teilen Sie die Datei auf! :-)

Auf meiner freebsd-Box (existiert auch für Linux und andere) habe ich ein Kommandozeilen-Dienstprogramm namens "Split".

 
usage: split [-l line_count] [-a suffix_length] [file [prefix]] 
     split -b byte_count[K|k|M|m|G|g] [-a suffix_length] [file [prefix]] 
     split -n chunk_count [-a suffix_length] [file [prefix]] 
     split -p pattern [-a suffix_length] [file [prefix]] 

So lief ich:

 
split -l 25000 -a 3 /data/var/myfile.log /data/var/myfile-log/ 

Dann landete ich mit 5608 Dateien im Verzeichnis/data/var/myfile-log/Verzeichnis, die dann könnte alles, was man zur Zeit mit einem Befehl verarbeitet werden wie:

 
php -f do-some-work.php /data/var/myfile-log/* 
Verwandte Themen