Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Out of Memory (https://www.delphipraxis.net/96973-out-memory.html)

simlei 2. Aug 2007 12:33


Out of Memory
 
Jaa ich hab gaanz viele Datensätze eingelesen (es waren etwa 23000 mit jeweils 16 string-Feldern), da kam nicht sehr überraschend "Out of Memory". Ich habe 2048 MB RAM, wo kann ich einstellen, dass Delphi mehr davon nutzt?

SirThornberry 2. Aug 2007 12:40

Re: Out of Memory
 
Das ist eigentlich sache des Betriebssystems. Es kommt hauptsächlich darauf an wie du den Speicher anforderst. In der Regel bekommt man das Problem wenn man zu viel Zusammenhängenden Speicher anfordert (Zum Beispiel bei einem Array etc.)

Der_Unwissende 2. Aug 2007 12:40

Re: Out of Memory
 
Hi,
wohin liest Du denn die Datensätze ein? An sich wird Delphi was den genutzen Speicher angeht nicht wirklich durch die Größe Deines RAM beschränkt. Vielmehr wird Speicher vom Betriebsystem angefordert und dieses lagert eben auch auf die Festplatte aus (virtuelle Speicher).
Hier wäre es schön, wenn Du kurz zeigen kannst, wie Du die Datensätze ausliest und sagst, was Du mit denen vor hast. Es sollte selten (oder gar nicht) nötig sein, dass Du wirklich 23.000 Datensätze gleichzeitig betrachten musst.

Gruß Der Unwissende

Bernhard Geyer 2. Aug 2007 12:41

Re: Out of Memory
 
Höhrt sich für mich nach einem Fehler/Problem des Standardmemory-Managers von Delphi (bis zu Version 2006) an.
Probier mal FastMM. Damit solltest du auch dein vermutlich noch im Programm vorhandnen Speicherlücken auch entdecken.

Luckie 2. Aug 2007 12:46

Re: Out of Memory
 
Gar nicht. Dein Prozess bekommt von Windows einen virtuellen Adressraum von effektiven 2 GB zugewiesen. Und das muss reichen. Mehr gibt es nicht. Du solltest also besser dein Design überdenken oder deine Speicherverwaltung überarbeiten.

simlei 2. Aug 2007 14:38

Re: Out of Memory
 
das System wurde gerade erst eingerichtet...
Ich lese sehr viele Kundendaten aus Outlook aus. Dabei müssen viele Emails verschmolzen werden (die Daten), ohne dass ich vorher weiß welche und wieviele. das erkenne ich erst wenn ich sie auslese (Schlüssel steht in den Mials selbst). Deshalb kann ich nicht einfach einen Teil abarbeiten und dann den nächsten nehmen, da _vielleicht_ das allererste und das allerletzte Item zusammengehören und ich sie so im Speicher halten muss.

Der_Unwissende 2. Aug 2007 14:48

Re: Out of Memory
 
Zitat:

Zitat von simlei
Ich lese sehr viele Kundendaten aus Outlook aus. Dabei müssen viele Emails verschmolzen werden (die Daten), ohne dass ich vorher weiß welche und wieviele. das erkenne ich erst wenn ich sie auslese (Schlüssel steht in den Mials selbst). Deshalb kann ich nicht einfach einen Teil abarbeiten und dann den nächsten nehmen, da _vielleicht_ das allererste und das allerletzte Item zusammengehören und ich sie so im Speicher halten muss.

Da solltest Du Dich mit der Idee eines Index beschäftigen. Ist eigentlich klassisch in jedem DBS zu finden! Du liest einfach die Datensätze ein und erstellst einen Index über die Schlüssel. Hier solltest Du einen Schlüssel finden können, der deutlich kleiner als der komplette Inhalt der Mail ist oder sind gerade die 16 String Felder Dein Schlüssel? Wichtig bei der Idee wäre, dass Du eben nicht die mails selbst im Speicher hälst, sondern nur die Liste der Schlüssel und Verweise auf alle mails zu einem Schlüssel (da sollte es schon dauern, bis Du 2 GByte voll bekommst!). Hast Du so vorsortiert, kannst Du dann gezielt immer zwei mails zusammenführen. Sollte Dein Index auch hier noch zu groß werden, dann unterteile weiter, verwalte z.B. einfach einen Präfixbaum, der wiederum die einzelnen Strukturen verwaltet, die eben alle einen Schlüssel haben der mit genau diesem Präfix beginnt (ausgehend davon, dass man im Mittel eine angenäherte Gleichverteilung hat).

SirThornberry 2. Aug 2007 14:52

Re: Out of Memory
 
wie bereits erwähnt kommt der Fehler in den meisten Fällen wenn große zusammenhängende Speicherbereiche angefordert werden.
Stell dir vor du hast insgesamt 2 GB platz. Alle 50 MB liegt ein Stück von einer Größe von einem Byte. Somit ist es jetzt nicht möglich ein zusammenhängendes Stück vom 100 MB zu bekommen weil ja alle 50 MB was dazwischen liegt.

Bei einigen Speichermanagern kann es aus diesem Grund auch zu dem Fehler kommen wenn du einen String immer wieder verlängerst.
Denn:
1.) String = 5 Zeischen liegt im Speicher bei Position 0
2.) Die Größe wird auf 6 Zeischen gesteigert => Ein neuer String von 6 Zeischen wird intern angelegt. Dieser beginnt an Position 5 (von 0 bis 4 liegt ja der alte string). Dann werd der alte 5 Zeischen lange String an den Beginn des 6 Zeischen langen Strings kopiert und der Speicherbereich von 0 bis 4 kann frei gegeben werden
3.) Die Größe wird auf 7 Zeischen gesteigert => Ein neuer String von 7 Zeischen wird intern angelegt. Dieser beginnt an Position 11 (von 5 bis 10 liegt ja der alte string und 0 bis 4 ist zu wenig platz). Dann werd der alte 6 Zeischen lange String an den Beginn des 7 Zeischen langen Strings kopiert und der Speicherbereich von 5 bis 10 kann frei gegeben werden.

So setzt sich das immer weiter fort. Resultat ist das du zwar freien Speicher hast aber eben irgendwann nicht mehr genügend zusammenhängenden Speicher.

simlei 2. Aug 2007 15:05

Re: Out of Memory
 
helfen da solche defrag-programme was (nicht für die festplatte jetzt ;) ) ?

SirThornberry 2. Aug 2007 15:11

Re: Out of Memory
 
da helfen keine Defrag-Programme. Da hilft die Verwendung eines anderen Speichermanager oder besser, die Verwendung eines algorythmus der das beachtet.
Zum Beispiel anstelle tausend mal an einen String etwas anzuhängen kann man vorher die benötigte Länge berechnen, 1 mal die Länge des Strings setzen und dann in diesen String (also in den Speicherbereich des Strings) die Daten rein kopieren.
negativ Beispiel:
Delphi-Quellcode:
var
  lCount : Integer;
  lquelle,
  lzeile : String;
begin
  lQuelle := 'abc';
  lZiel  := '';
  for lCount := 0 to 999 do
  begin
    lZiel := lZiel + lQuelle;
  end;
besser:
Delphi-Quellcode:
var
  lCount,
  lLenQuelle : Integer;
  lquelle,
  lzeile   : String;
begin
  lQuelle := 'abc';
  lLenQuelle := Length(lQuelle);
  SetLength(lZiel, 1000 * lLenQuelle);
  for lCount := 0 to 999 do
  begin
    move(lQuelle[1], lZiel[1 + lCount * lLenQuelle], lLenQuelle);
  end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:05 Uhr.
Seite 1 von 2  1 2      

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