Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi dynamisches Array -> setLength Problem (https://www.delphipraxis.net/16105-dynamisches-array-setlength-problem.html)

Wegalt 10. Feb 2004 13:30


dynamisches Array -> setLength Problem
 
Hallo,

ich habe ein Problem mit dem Speicher, welches mein Array braucht.

1. Wenn ich von vornerein weiß wie groß mein Array werden soll und dieses im Vorfeld auf die richtige größe setze, wird relativ wenig Speicher gebraucht

2. Wenn ich aber mein Array in der Größe immer um eins erhöhe frißt dieses unmengen von Arbeitsspeicher.

Delphi-Quellcode:
procedure TForm1.setArray; //Testbeispiel
var i: integer;
begin
 //zu 1. setlength(hallo,5,StrToInt(edit1.Text)+1);
 for i :=0 to strtoint(Edit1.Text) do
 begin
 //zu 2. setlength(hallo,5,i+1);
 hallo[0,i] := 'test12345678 '+ inttostr(i);
 hallo[1,i] := 'test12345678 '+ inttostr(i);
 hallo[2,i] := 'test12345678 '+ inttostr(i);
 hallo[3,i] := 'test12345678 '+ inttostr(i);
 hallo[4,i] := 'test12345678 '+ inttostr(i);
 Application.ProcessMessages;

 Label1.caption := inttostr(i);
 end;

end;
Gibt es eine Möglichkeit mein Array zu reorganisieren und damit den Speicherverbrauch zu senken, ohne das ich die Daten in ein weiteres Array kopieren muß, also in eins wo die größe vor der Befüllung feststeht?

Gruß
Wegalt

Chewie 10. Feb 2004 13:40

Re: dynamisches Array -> setLength Problem
 
Wenn du die Größe eines Arrays änderst, wird der ganze Krams, der vorher in dem Array nicht drin war, an eine andere Stelle im Speicher kopiert. Es kann dabei vorkommen (und es kommt vor), dass der Speicher, den das Array vorher belegte, nicht freigegeben wird. Deshalb der erhöhte Speicherverbrauch.

Man kann diese Effekt minimieren, wenn man immer segmentweise das Array vergrößert, also nicht immer um 1 größer, sondern um einen konstanten Wert (z.B. 100) oder um eine Prozentangabe (z.B. 10%). Das erfordert natürlich einen etwas höheren Verwaltungsaufwand, da High(Array) nicht mehr unbedingt die Obergrenze des Geschriebenen darstellt, aber erhört die Performance und spart Speicherplatz.

jbg 10. Feb 2004 13:44

Re: dynamisches Array -> setLength Problem
 
Zitat:

Zitat von Wegalt
Wenn ich aber mein Array in der Größe immer um eins erhöhe frißt dieses unmengen von Arbeitsspeicher.

Grob geschätzt frißt das Array dann Fakultät(Length(A)) * SizeOf(A[0]) Bytes.

Zitat:

Gibt es eine Möglichkeit mein Array zu reorganisieren und damit den Speicherverbrauch zu senken, ohne das ich die Daten in ein weiteres Array kopieren muß, also in eins wo die größe vor der Befüllung feststeht?
Du könntest so arbeiten, wie es TList und TStringList macht. Einfach das Array um einen festen Delta-Wert erhöhen und eine Variable Len mitlaufen lassen, die die effektive Länge des Arrays enthält. Zum Schluss setzt du dann die tatsächliche Länge des Arrays auf die effektive Länge.

Wegalt 10. Feb 2004 13:51

Re: dynamisches Array -> setLength Problem
 
Das ist mir auch schon eingefallen, ist aber nicht besonders elegant!
Es scheint als würde das Array mit jedem setLength mit der neuen Größe
kopiert und das alte nicht nicht wieder frei gegeben wird.
Man könnte evtl 2 Arrays benutzen und die Daten immer von einem ins andere kopieren und dann jeweils das ungenutzte leeren. Gefällt mir aber auch nicht!

Es wundert mich nur das trotz diesem Problem so viel mit setlength experimentiert wird!!

X-Dragon 10. Feb 2004 13:58

Re: dynamisches Array -> setLength Problem
 
Zitat:

Zitat von Wegalt
Das ist mir auch schon eingefallen, ist aber nicht besonders elegant!
... Es wundert mich nur das trotz diesem Problem so viel mit setlength experimentiert wird!!

Naja es kommt halt immer auf die Umstände an. Bisher war es bei mir meistens so das ich vorher die genaue Zahl der Einträge feststellen konnte und dann erst das Array in der passenden Größe erstellt habe. Ausserdem muss man sich natürlich immer fragen ob der Aufwand (dyn. erweitern des Arrays) sich für den max. notwendigen Speichverbrauch wirklich lohnt. Also in meinen Anwedungen ist mir bisher noch nichts vergleichbares aufgefallen (wobei es aber auch sehr selten so nutze).

Mario 10. Feb 2004 13:58

Re: dynamisches Array -> setLength Problem
 
Ich nutze SetLength auch sehr intensiv, habe aber solche Probleme noch nie gemerkt. Das kann mehrere Ursachen haben:

Fehler in der Delphi-Version? Ich nutze Delphi 6.02

Bei mir ist es, ich habe es aber nie gemerkt

Wenn die Objekte, wo das Array zugehört, freigegeben werden, so wird der Speicher doch wieder korrekt freigegeben.

Letzteres könnte evtl. den Ausschlag geben, wissen tue ich es nicht. Der Großteil der SetLengths ist in meinen Programmen in kurzlebigen Objekte drin...

Wegalt 10. Feb 2004 14:18

Re: dynamisches Array -> setLength Problem
 
Also Delphi abhängig scheint es nicht zu sein. Ich nutze Delphi 5 und 7.

Grundsätzlich tritt das Problem natürlich nur ab vielen Datensätzen auf.
Also wenn man 10tausende einfügt ist der Speicher rats bats voll.

Wenn man das Array wieder auf null setzt wurde auch der gesamte Speicher freigegeben.
Bei der 2. Version dauert es natürlich um längen länger ihn freizugeben.

jbg 10. Feb 2004 15:50

Re: dynamisches Array -> setLength Problem
 
Durchsucht mal das Forum. Dort haben schon mehrere (mich eingeschlossen) dieses Phänomen erklärt.

Um es kurz zu machen:
Konstruktor wie
Delphi-Quellcode:
for i := 0 to 100000 do
  SetLength(A, Length(a) + 1);
und
Delphi-Quellcode:
for i := 0 to 100000 do
  S := S + 'x';
machen im Hintergrund fast genau dasselbe.
Und gemeinsam haben sie, dass sie den Delphi Speichermanager mishandeln. Dieser reserviert nämlich den Speicher in Blöcken von Windows und wenn FreeMem aufgerufen wird, wird dieser Speicher nur wieder an Windows zurückgegeben, wenn der zusammenhängende Block frei ist. Ansonsten merkt sich der Delphi Speichermanager die Position und die Größe des freigegebenen Speicherbereichs um ihn schneller wieder zur Verfügung zu stellen als es Windows je könnte.


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:12 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz