[quote=murphy,08.April.2006, 02:21][quote=ptk,07.04.2006, 20:08][...] Aber intern muss, falls kein Platz mehr vorhanden ist, das gesamte Array umkopiert werden (bei einer echten Liste ist das nie notwendig).[/quote]
Ja, das kann passieren. Kommt es sehr auf die Performance an, kann man die aber die Größe des Arrays, bevor man zum Beispiel viele einzelne Elemente einfügt, festlegen indem man $#array eine Zahl zuweist.[/quote]
Dazu hätte ich dann mal eine Frage.
Wenn ich also die Größe mit "$#array = xxx" nicht festlege, und ich ein push ausführe, dann müsste doch rein theoretisch für jedes weitere push das array umkopiert werden, und die größe um eins erhöht werden? Wenn ich das mit 3Mio. Elementen mache dann sollte man doch einen deutlichen Performance unterschied Merken.
Hierzu habe ich dann also paar Tests gemacht. Mein Skript sah erstmal folgendermaßen aus.
#!/usr/bin/perl -w
use Time::HiRes 'time';
$string = "x" x 3_000_000;
my @array;
#$#array = 3_000_010;
$start = time();
@array = split( //, $string );
$end = time();
printf "Die Zeit Betrug %lf Sekunden\n", $end - $start;
printf "Das Array hat %d Eintraege\n", scalar @array;
Ich initialisiere einen String der 3 Mio. 'x'e enthält, und schiebe danach jedes x in einem array hinein.
Als ich das so ausführte gab das bei mir ca. 3,3 Sekunden laufzeit. Und das Array ist 3 Mio. Eintraege groß.
Danach habe ich die Grenze mit "$#array" auskommentiert. Das Ergebnis ist wieder 3.3 Sekunden. Und 3 Mio. Eintraege. Aber eigentlich müssten doch 3Mio+10 Eintraege vorhanden sein? So dachte ich mir das jedenfalls. Anscheind wird bei einer direkt zuweisung die maximal Größe des Arrays wieder gelöscht, und dann neu zugewiesen. Eigentlich ja logisch, wäre ja blöd wenn ich bei einer direkten zuweisung noch Werte aus der vorherigen zuweisung noch im array hätte. Hier bringt also eine Zuweisung mittels "$#..." nichts.
Danach habe ich dann anstatt einer direkten Zuweisung ein push genommen. Jedoch habe ich erstmal die zuweisung der maximalen größe "$#..." weg gelassen.
Dafür habe ich dann anstatt er Zuweisung folgende Zeile geschrieben.
push @array, split( //, $string );
Anscheind ist ein push schneller. Hier bekomme ich 2.7 Sekunden laufzeit heraus.
Danach habe ich die Maximale größe mittels "$#..." gesetzt. Das Ergebnis ist das es wieder 2.7 Sekunden sind. Allerdings ist das Array jetzt 6Mio.+11 Eintraege groß.
Mit "$#..." setzte ich anscheind die Größe. Allerdings zeigt ein Pointer wohl auf diese Stelle. Und ein Push benutzt anscheind diesen Pointer und hängt dann an dieser Position etwas an. Allerdings weiß ich nicht wie ich bei Perl den Pointer wieder auf der ersten Stelle setze? Vielleicht kann mir das einer sagen?
Allerdings wäre die Verwendung von "push" ja dann unsinnig. Es würde ja nichts mehr am Array anhängen.
Also ein normales setzen von "$#..." bringt eigentlich nichts. Den mit einer Zuweisung wird das Array komplett neu erstellt. Die maximale größe wird also überschrieben. Und mit einem Push hängt man ja wie gesagt nur etwas an. Man vergößert dann das array nochmals. Also müsste hier eigentlich auch wieder das gesamte Array umkopiert werden.
Da ich dann aber schon 6Mio. Eintrage habe die umkopiert werden. Müsste doch eigentlich eine Zuweisung schneller sein. Denn bei einer Zuweisung muss ich ja immer nur 3 Mio. Eintrage umkopieren. Bei einen Push muss ich dann immer 3Mio. Eintrage plus jeden Schleifendurchlauf einen Wert mehr umkopieren, bis zum Ende 6 Mio. Werte. Die zeit bleibt aber trotzdem auf 2.7 Sekunden. Von daher sieht es nicht so aus, dass etwas umkopiert werden muss.
Das einzige was etwas bringen könnte wäre wenn man die Größe festlegt und dann in einer Schleife jedes element neu setzt.
Also habe ich folgendes geschrieben
use Time::HiRes 'time';
my @array;
#$#array = 3_000_010;
$start = time();
for( 1 .. 3_000_000 )
{
$array[$_] = 'x';
}
$end = time();
printf "Die Zeit Betrug %lf Sekunden\n", $end - $start;
printf "Das Array hat %d Eintraege\n", scalar @array;
Die Laufzeit beträgt hier 1.8 Sekunden bei mir. Allerdings macht es bei mir keinen Unterschied ob ich nun vorher die maximale Größe mittels "$#..." gesetzt habe, oder nicht.
Für mich sieht das jedenfalls aus, als wenn das Arrays doch nicht jedesmal neu umkopiert werden muss? Und es sieht eher wie ein Listenverhalten aus.
Klärt mich auf! ^^
Oder habe ich gerade einen Denkfehler?\n\n
<!--EDIT|sid burn|1144591977-->
Nicht mehr aktiv. Bei Kontakt: ICQ: 404181669 E-Mail: perl@david-raab.de