Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Wieviele Daten passen in ein dynamisches Array? (https://www.delphipraxis.net/76938-wieviele-daten-passen-ein-dynamisches-array.html)

Nuclear-Ping 12. Sep 2006 12:25


Wieviele Daten passen in ein dynamisches Array?
 
Hallo ihr,

ich arbeite gerade an einem Projekt, wo kurz gesagt ein dynamisches Array of Byte im Laufe einer Analyseroutine mit Daten zur späteren Auswertung gefüllt wird und dabei immer weiter wächst.

Das Problem ist nun, dass mein Programm nach ca. 6MB Daten im Array mir eine "Nicht genügend Arbeitsspeicher"-Exception um die Ohren haut.

Die Analyseroutine lässt sich mit verschiedenen Optionen fahren, sodass einmal mehr und einmal weniger Daten in das Array kommen. Dabei spielt es keine Rolle, wie lange diese Routine läuft, sondern wieviel Daten das Array bekommt. "Option 1" produziert dabei diesen Fehler. Und die gleiche Routine kann 5min mit "Option 2" (die weit weniger Daten produziert) erfolgreich durchlaufen, ohne Probleme.

Ist das normal? Sollte doch eigentlich egal sein, wieviel Daten das Array aufnimmt, solange genügend (virtueller) Speicher zur Verfügung steht, oder nicht? Auf C sind noch 23GB frei, die Auslagerungsdatei ist auf 1,5GB eingestellt, das System hat 512 MB RAM.

xaromz 12. Sep 2006 12:32

Re: Wieviele Daten passen in ein dynamisches Array?
 
Hallo,

wie wächst denn Dein Array? Da kann man viel falsch machen.

Gruß
xaromz

Nuclear-Ping 12. Sep 2006 12:34

Re: Wieviele Daten passen in ein dynamisches Array?
 
Delphi-Quellcode:
// *****************************************************************************
// TAudioScannerSimple
// *****************************************************************************

function TAudioScannerSimple.BufferFilled (Buffer: PChar; var Size: Integer): Boolean;
var
  a, b, c: Integer;
  BitStr3: String;
begin
  for a := 0 to Size do
    begin
      BitStr3 := ByteToBitStr (Byte (Buffer[a]));
      for b := 1 to Length (BitStr3) do
        inc (FBitsValCount[strtoint (BitStr3[b])]);
    end;

  a := Length (FAudioBuffer);
  SetLength (FAudioBuffer, a + Size);
  for b := 0 to Size - 1 do
    FAudioBuffer[a + b] := Byte (Buffer[b]);
   
  FBufferFilled := TRUE;
end;
Das ist ein Event, der von der TAudioIO-Komponente aufgerufen wird, wenn der interne Buffer (1024 Bytes) voll ist. Die Daten werden an ein Array (FAudioBuffer) in der Klasse angehängt.

Edit: Ich seh gerade, dass ich hier einen Fehler hab: for a := 0 to Size do - Es müsste " to Size - 1 do" heissen. Gerade korrigiert und teste es.

Edit2: Daran lag es nicht. Bekomme immernoch den Fehler. In der Unit System.pas, procedure DynArraySetLength, Zeile 16273: ReallocMem(pp, neededSize);

Union 12. Sep 2006 12:54

Re: Wieviele Daten passen in ein dynamisches Array?
 
Also bei mir läuft es ohne Probleme, sogar bis zu 3 Mio. Durchläufen mit einer Puffergröße von 11 (Länge des Array 33000011, Speicherbedarf 36,3 MB, 1024 MB Hauptspeicher) . Allerdings habe ich den ersten Teil auskommentiert, da mit die aufgerufenen Funktionen (ByteToBitStr)nicht vorliegen. Vielleicht müllt dieser Teil etwas zu? Und warum übergibts Du Size als var? Wird doch in der Funktion nicht geändert...
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
   i : integer;
   AudioScanner : TAudioScannerSimple;
   Size : integer;
begin
   AudioScanner := TAudioScannerSimple.Create;
   Size := 11;
   for i := 0 to 3000000 do
   begin
      AudioScanner.BufferFilled(pchar('ABCDEFGHIJK'), Size);
      if i mod 10000 = 0 then
      begin
         Label1.Caption := inttostr(i)+'/'+inttostr(length(Audioscanner.Audiobuffer));
         Application.ProcessMessages;
      end;
   end;
end;

Bernhard Geyer 12. Sep 2006 13:00

Re: Wieviele Daten passen in ein dynamisches Array?
 
Ich denke du fährst in das Verwaltungsfragmentierungsproblem des Default-Memorymanagers von Delphi. Lade dir FastMM von Sourceforge und nimm dieses. Damit konnten wir auch ähnliche Probleme lösen. Und unser Programm ist schneller geworden :-)

Aber du solltest dir überlegen ob ein dynamisches Array als interer Buffer die beste Lösung darstellt. Wäre ein TMemoryStream nicht besser?

Union 12. Sep 2006 13:06

Re: Wieviele Daten passen in ein dynamisches Array?
 
Zitat:

Wäre ein TMemoryStream nicht besser?
Der läuft in die gleichen Probleme rein, denn er greift ja auch auf den Memory Manager zu. Eine Lösung wäre es, das Array oder den Stream am Anfang auf die vermutete Endgröße zu setzen, sonst wird alle paar Bytes versucht den Speicher zu realloziieren.

Auch ist vielleicht generell ein Array of byte nicht die tollste Lösung, da hier der Verwaltungsoverhead die "Nutzlast" bei weitem übersteigt.

Aber das geht wieder am eigentlichen Problem vorbei. Er hatte gesagt, er erhielte einen Speicherfehler. Dies konnte ich (s.o.) nicht nachvollziehen. Man bräuchte schon die fehlenden Funktionen um den Ablauf vollständig testen zu können.

marabu 12. Sep 2006 13:13

Re: Wieviele Daten passen in ein dynamisches Array?
 
Hallo Mario,

ich würde die buffer segments in einer Liste ablegen. Zusammenschieben kannst du sie immer noch, wenn es denn irgendwann nötig ist.

Der Code am Anfang zählt die Nullen und Einsen?

Delphi-Quellcode:
var
  iByte, iBit: Integer;
  b: Byte;
  pb: PByte;
begin
  pb := PByte(Buffer);
  for iByte := 1 to Size do
  begin
    b := pb^;
    for iBit := 1 to 8 do
    begin
      Inc(FBitsValCount[b and 1]);
      b := b shr 1;
    end;
    Inc(pb);
  end;

  bl.Add(Buffer); // immer 1024 Byte?
  Result := False;
end;
Grüße vom marabu

himitsu 12. Sep 2006 14:42

Re: Wieviele Daten passen in ein dynamisches Array?
 
Ich würde dir bei vielen Größenänderungen eine Schrittweise änderung ämpfehel und die Tatsächliche Größe extra speichern.
Unter Umständen kann man sons nette Fragmentierungsprobleme bekommen, vorallem bei DelphiMM.

Delphi-Quellcode:
Type TArray = Record
    Size: Integer;
    Data: Array of Byte;
  End;

Var MyArray: TArray;


//Und dann eventuell ein eigenes SetLength (hier wird z.B. auf 64 KB aufgerundet)
Procedure MySetLength(Var A: TMyArray; NewSize: Integer);
  Begin
    A.Size := NewSize;
    SetLength(A.Data, (NewSize + $FFFF) and $00010000);
  End;
Length(EinArray) wird dann durch MyArray.Size
und EinArray[123] durch MyArray.Data[123] ersetzt.

Man kann die Variablen zwar auch einzeln Verwalten, aber zusammen ist es wohl schöner ^^
Obwohl man so nur die SetLength und Length umbauen müßte. (am Array selber ändert sich da ja nichts)
Delphi-Quellcode:
Var ASize: Integer;
  AData: Array of Byte;

Nuclear-Ping 12. Sep 2006 15:14

Re: Wieviele Daten passen in ein dynamisches Array?
 
Danke für eure Beiträge.

Warum Size als Var übergeben wird, kann ich nicht sagen. Ist halt die Header-Definition der Prozedur von der Komponente. :D

Der Code am Anfang zählt Nullen und Einsen, um ein Verhältnis zwischen ihnen darzustellen, ist aber für den eigentlichen Ablauf nicht wichtig. Hab den Teil gerade mal auskommentiert und lass das Programm nochmal laufen. Ist gerade bei 4MB.

Hm, OK, bei 5.710.848 Bytes fliegts mir wieder um die Ohren.

Ich werde nun mal den FastMM testen und mich wieder melden.

Na mei, mit dem FastMM lief er zum ersten mal durch. Die Endgröße des Puffers war nach dem Durchlauf 10MB. :dance: Danke für den Tip, Bernhard. Werde den guten hier noch etwas Stress-Testen, solange laufen lassen wie es geht.

Werde aber auch mal schauen, wie ich den Tip mit der Liste verbauen kann.

:cheers:

himitsu 12. Sep 2006 16:51

Re: Wieviele Daten passen in ein dynamisches Array?
 
Ach ja, in ein dynamisches Array passen maximal 2 GB - 1 Byte (abgesehn, daß vorher der Speicher ausgehen könnte :roll:

Nuclear-Ping 12. Sep 2006 19:22

Re: Wieviele Daten passen in ein dynamisches Array?
 
Ich hoffe, soweit kommt es nicht. Währe theoretisch zwar möglich, wird aber praktisch wohl nicht passieren.

Hab ihn gerade mal mehrere Stunden laufen lassen (war nicht da) und bei 31MB hat er mir einen "Systemfehler 14 - Für diesen Vorgang ist nicht genügend Speicher verfügbar" gebracht.

Werde daran aber mal rumtüfteln. Hab ja nun genug heiße Spuren und mich ggf. nochmals melden.

Danke auf jeden Fall an alle nochmal, für eure Hilfe!

himitsu 13. Sep 2006 11:32

Re: Wieviele Daten passen in ein dynamisches Array?
 
Hmmm, selbst durch 'ne "gute" Speicherfragmentierung sollte DelphiMM nicht so leicht über's 4 bis 5-fache kommen :gruebel:

Ich hatte es ja auch nur unter "Optimalbedingungen" mit realen 12 MB geschaft etwa 600 MB zu belegen ._.

Auch wenn der Task Manager nicht unbedingt richtige Werte liefert ... was zeigt der denn an? (RAM, Virtuell usw.)


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:08 Uhr.

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