Hello, On Mon, 23 Jun 2003, Ralf Corsepius wrote:
Am Mon, 2003-06-23 um 03.00 schrieb David Haller: [..]
Das ist der gleiche Fehler wie von grepmail. Versuch das mal mit ner Datei von ein paar 100 MB!!! 100MB Dateien sind ein extremer Sonderfall.
Nicht bei grepmail... Das Teil frisst (oder frass zumindest) Speicher wie bekloppt. Je nach Hauptspeicher geht's halt ab einer gewissen Dateigroesse nicht mehr...
Ja, bei derartigen Extremfällen scheitert Einlesen in eine einzelne Liste, aber ... [..]
foreach (@zeilen) { # Zeilen abklappern, Zeile wird in $_ abgelegt
*ARGH* Hier wird's dann wirklich doof, wenn man sowieso zeilenweise liest, kann man gleich die Datei hernehmen.
... Jan's Lösung ist schon bei Dateien mit wenigen 100 Zeilen um mehrere 10-Potenzen schneller.
*huch* ;) Aehm, nunja, siehe unten.
D.h. je nach Anwendungsgebiet ist mal die eine oder die andere Lösung sinnvoller, schneller oder "besser".
Ack. Es wurde halt nix zur Dateigroesse gesagt, und bevor z.B. ein script wg. Speichermangel gar nicht laeuft, soll's ruhig etwas laenger laufen... So, nun interessiert mich das jetzt aber mal... ;) Ich hab mir mal ein paar Testdaten angelegt (script s.u.)... dh@slarty[3]: ~/src/perlbenches (0)$ ls -lh total 120M -rwxr--r-- 1 dh dh 2.0k Jun 24 00:05 dat2html_dh.pl -rwxr--r-- 1 dh dh 2.0k Jun 24 00:05 dat2html_dh_foreach.pl -rwxr--r-- 1 dh dh 2.0k Jun 24 00:05 dat2html_dh_noprint.pl -rwxr--r-- 1 dh dh 1.8k Jun 24 00:04 dat2html_jan.pl -rwxr--r-- 1 dh dh 704 Jun 23 23:36 gendata.pl -rw-r--r-- 1 dh dh 1.1k Jun 23 23:36 set1.dat -rw-r--r-- 1 dh dh 9.1k Jun 23 23:36 set2.dat -rw-r--r-- 1 dh dh 93k Jun 23 23:36 set3.dat -rw-r--r-- 1 dh dh 990k Jun 23 23:36 set4.dat -rw-r--r-- 1 dh dh 10M Jun 23 23:36 set5.dat -rw-r--r-- 1 dh dh 108M Jun 23 23:36 set6.dat dh@slarty[3]: ~/src/perlbenches (0)$ tail -2 dat2html_* ==> dat2html_dh.pl <== print STDERR `cat /proc/$$/status`; exit 0; ==> dat2html_dh_foreach.pl <== print STDERR `cat /proc/$$/status`; exit 0; ==> dat2html_dh_noprint.pl <== print STDERR `cat /proc/$$/status`; exit 0; ==> dat2html_jan.pl <== print STDERR `cat /proc/$$/status`; exit 0; dh@slarty[3]: ~/src/perlbenches (1)$ for s in dat2html_*; \ do \ echo "==== $s ====" >&2; \ for i in `seq 1 5`; \ do \ echo "set$i: " >&2; \ time perl $s "set${i}.dat" >/dev/null; \ done; \ done 2>&1 \ | awk '/^=/{print;}/^set/{t=$0;}/^VmSize/{t=t $0;}/real/{print t," ",$0}' ==== dat2html_dh.pl ==== set1: VmSize: 2800 kB real 0m0.095s set2: VmSize: 2808 kB real 0m0.152s set3: VmSize: 2808 kB real 0m0.606s set4: VmSize: 2812 kB real 0m5.527s set5: VmSize: 2812 kB real 0m51.129s ==== dat2html_dh_foreach.pl ==== set1: VmSize: 2800 kB real 0m0.064s set2: VmSize: 2856 kB real 0m0.134s set3: VmSize: 3428 kB real 0m0.602s set4: VmSize: 8960 kB real 0m5.517s set5: VmSize: 72648 kB real 0m54.077s ==== dat2html_dh_noprint.pl ==== set1: VmSize: 2800 kB real 0m0.188s set2: VmSize: 2808 kB real 0m0.099s set3: VmSize: 2808 kB real 0m0.493s set4: VmSize: 2812 kB real 0m4.259s set5: VmSize: 2808 kB real 0m41.551s ==== dat2html_jan.pl ==== set1: VmSize: 2800 kB real 0m0.063s set2: VmSize: 2856 kB real 0m0.128s set3: VmSize: 3424 kB real 0m0.559s set4: VmSize: 8952 kB real 0m4.777s set5: VmSize: 72636 kB real 0m47.534s Ei, gugge mol do... Nein, ich bin nicht ueberrascht ;) Ich glaube dir ja in der Regel, aber dass die 'while(<DATEI>)' Variante soo viel laenger brauchen sollte haette mich doch sehr gewundert... Also: ja, die "foreach" Variante ist marginal schneller, deine "mehere 10-Potenzen"[1] sind aber definitiv nicht nachvollziehbar. Und wenn man dann noch den Speicherverbrauch einbezieht, ist meine Meinung "*AAAAA*" nachvollziehbar gerechtfertigt. Der Speicherverbrauch bei "while(<DATEI>)" ist quasi konstant, im Gegenteil zu "@array=<DATEI>; foreach(@array);". Und ja, "set5" ist tatsaechlich nur mit der 10M Datei; auch noch set6 zu testen hat mir zu lange gedauert. Man achte insbesondere auf den Unterschied zwischen _dh.pl und _dh_foreach.pl, da der Unterschied (s.u.) der beiden scripte wirklich nur aus der Art besteht, wie die Datei eingelesen wird. Interessanterweise ist die foreach-Variante sogar langsamer, sobald die zu verarbeitende Datei groesser wird! -dnh PS: perl 5.8.0, selbst kompiliert PPS: bei Bedarf kann ich auch ein tar der Scripte mailen. [1] es ist ja nur eine ca. 7% laengere Laufzeit. Das ist nicht immer ein relevanter Unterschied, v.a. wenn man sich den Speicherverbrauch anschaut. ==== gendata.pl [quick & dirty, Performance egal] ==== #! /usr/bin/perl -w my @testcases = [ q[ Kdnr: 1211 Name: Schmitz, Peter Firma: Schmitz GmbH Beschreibung: Projekt XY, Netzwerkverkabelung Telefon: 0123 45678 Zusatz: Kunde will Angebot für VPN ], q[ Kdnr: 1219 Name: Müller, Franz Firma: Müller & Söhne GbR Beschreibung: Projekt AB, Datensicherung Beschreibung: Datensicherung Windows NT-Server Telefon: 0123 45678 ] ]; my ($i, $dat); for my $i ( 1 .. 6 ) { open(DAT, ">set$i.dat") or die $!; foreach(@testcases) { print DAT @{$_}; for( 1 .. (10 ** $i) ) { print DAT qq[ Kdnr: $_ Name: Name$_, $_ Firma: firma$_ Beschreibung: Beschreibung$_ Telefon: telefon$_ ]; } } close(DAT); } ==== ==== diffs fuer die Varianten ==== dh@slarty[3]: ~/src/perlbenches (1)$ diff -U1 dat2html_dh.pl dat2html_dh_noprint.pl --- dat2html_dh.pl Tue Jun 24 00:05:12 2003 +++ dat2html_dh_noprint.pl Tue Jun 24 00:05:03 2003 @@ -43,3 +43,3 @@ # ausgeben... - print_row(); + # print_row(); # ... und den hash reinitialisieren @@ -67,3 +67,3 @@ # letzten Satz auch noch ausgeben... -print_row(); +# print_row(); # ...und die Tabelle "schliessen" dh@slarty[3]: ~/src/perlbenches (1)$ diff -U1 dat2html_dh.pl dat2html_dh_foreach.pl --- dat2html_dh.pl Tue Jun 24 00:05:12 2003 +++ dat2html_dh_foreach.pl Tue Jun 24 00:05:08 2003 @@ -27,2 +27,4 @@ open(DATEI, "<$ARGV[0]") or die "Fehler beim Oeffnen der Datei: $!"; +my @zeilen = <DATEI>; +close(DATEI); @@ -36,3 +38,3 @@ -while(<DATEI>) { # Zeilen abklappern, Zeile wird in $_ abgelegt +foreach(@zeilen) { # Zeilen abklappern, Zeile wird in $_ abgelegt next if /^\s*$/; # leere Zeilen wegschmeissen @@ -64,3 +66,2 @@ } -close(DATEI); ==== Und wie gesagt, ich hab in allen 4 scripten noch das print STDERR `cat /proc/$$/status`; eingefuegt, ansonsten entsprechen die scripte den gemailten Versionen. -- Das Problem ist vermutlich auf schlechte Erdung zurueckzufuehren. Schlagt einfach zwei Stahlnaegel in die Turnschuhe eures MCSEs. So koennen die Ueberspannungen aus dem Kopf abfliessen, und Euer Mann achtet auch mehr auf seine Sicherheit in der Naehe von Computern. -- M. Liss in dasr