AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

Speicher sparen und Geschwindigeit erhöhen

Ein Thema von mika · begonnen am 14. Feb 2003 · letzter Beitrag vom 18. Feb 2003
Antwort Antwort
Seite 1 von 2  1 2   
Benutzerbild von mika
mika

Registriert seit: 25. Okt 2002
176 Beiträge
 
Delphi 6 Professional
 
#1

Speicher sparen und Geschwindigeit erhöhen

  Alt 14. Feb 2003, 12:38
Hallo alle!

ich hab mal wieder ein neues Problem. Ich habe vor einen Urlaubsplaner
zu schreiben, das Problem ist auch nicht der Code oder die Logik oder so.
Ich habe das Problem das mein Urlaubsplaner recht langsam ist, und je
mehr elemente ich in mein Dynamisches Array hänge desto länger braucht
er um ein einzelnes Element anzuhängen. Ich habe mir ausgerechnet was
ein Objekt anhand meiner Variablen für Speicher verbrauchen würde.
Aber wenn ich meinen verbrauchten Speicher nach dem laden durch die
anzahl der tage*personen teile bekomme ich einen viel größeren wert für
ein element raus

Meine beiden Probleme sind also die typischen: Wie spare ich Speicher und
wie bekomm ich den ganzen kram schneller? anstatt eines dynamischen arrays
eine tlist benutzen? oder doch lieber selber ne zweifach verkettte
dynamische liste (müsste vom prinzip ja sowas sein wie die tlist, halt
bloss selber)? ich weiss da echt nicht weiter.

Ich habe getestet auf ner guten maschine (p4-2ghz,256mb) und er hat bei
11 personen für das ganze jahr 2003 8mb speicher verballert und 15 sek.
gebraucht. bei 70 personen habe ich nach 5 minuten und 150mb das
programm abgebrochen (

nachstehend mal n bisschen code:


Delphi-Quellcode:

type

  TMyCoords = Packed Record
    Column: Word;
    Row: Word;
    Top: Word;
    Left: Word;
    Bottom: Word;
    Right: Word;
  End;

  TMyInformation = Packed Record
    msdDay: TDate;
    msdWDay: String[12];
    msdPerson: String[50];
    msdPersonNR: String[5];
    msdActualKosten: String[5];
    msdNormalKosten: String[5];
  End;

  TMySpecialDay = class(TShape)

    mytitel: TStaticText;
    constructor NCreate ( how: TCreateIt ); // Constructor
    destructor Destroy; override; // Destructor

    private
      msdID: Integer;
      msdState: Word;
      // ---
      msdCoords: TMyCoords;
      msdInfo: TMyInformation;
      // ---
      msdChanged: Boolean;
      msdStatebeforeChange: Word;
      msdSelected: Boolean;
      public
      procedure onMyMouseDown(Sender: TObject; Button: TMouseButton;
                              Shift: TShiftState; X, Y: Integer);
      procedure onMyMouseMove(Sender: TObject; Shift: TShiftState; X,
                              Y: Integer);
      procedure onMyMouseUp(Sender: TObject; Button: TMouseButton;
                            Shift: TShiftState; X, Y: Integer);
      procedure CreateLabel(var Lbl: TStaticText;
                                X,Y,W,H: Integer;
                                BorderStyle: TStaticBorderStyle;
                                Color,FontColor: TColor;
                                FontStyle: TFontStyles;
                                Capt: String;
                                Align: TAlignment;
                                FontSize: Integer);
  end;

var
  mySD: Array of TMySpecialDay;
erstellen tu ich das ganze über meinen constructor und indem ich
das array mit setlength(length + 1) erhöhe.

Weiss da jemand Rat?
mfg, Mika
:: don't Panic ::
  Mit Zitat antworten Zitat
lodda

Registriert seit: 6. Dez 2002
65 Beiträge
 
Delphi 5 Standard
 
#2
  Alt 14. Feb 2003, 13:06
Hallo mika

wass machst du wenn du das Array vergrößerst?
  Mit Zitat antworten Zitat
jbg

Registriert seit: 12. Jun 2002
3.479 Beiträge
 
Delphi 10.1 Berlin Professional
 
#3
  Alt 14. Feb 2003, 14:09
Der Delphi-Speichermanager hat ein Problem, wenn man ein Array laufend vergrößert.

Hier mal zur Verdeutlichung:

1. Code:
Delphi-Quellcode:
SetLength(100000);
for i := 0 to 100000 - 1 do
  a[High(a)] := TMyObject.Create;
2. Code:
Delphi-Quellcode:
a := nil;
for i := 0 to 100000 - 1 do
begin
  SetLength(a, Length(a) + 1);
  a[High(a)] := TObject.Create;
end;
Das Ergebnis beider Codes ist identisch. Der Speicherverbrauch hingegen nicht. Rein rechnerisch kommt man beim Speicherverbrauch zwar auf diesselben Werte, aber die Realität zeigt etwas anderes:

1. Code: a belegt ca. 4 MB
2. Code: a belegt ca. 120 MB


Das ganze hat mit Speicherlöchern zu tun. So wird beim 1. Code der gesamte Speicher für das Array auf einmal belegt. Beim 2. Code hingegen wird immer wieder vergrößert. Dieses Vergrößern hat zur Folge, dass das neue Array nicht mehr in den alten Speicherbereich passt und somit ein neuer, der das Array aufnehmen kann, reserviert werden muss. Der alte bleibt aber für Windows belegt, da Delphi diesen nicht freigibt, weil er ja Programmintern wieder verwendet werden kann. Nur eben nicht von unserem Array, das zu Groß dafür ist. Da sich aus diesem Grund der Speicherverbrauch der Anwendung immens erhöht, bleibt Windows kein RAM mehr und es muss auslagern, was die Performance in die Knie zwingt.

Wenn man jedoch auf des "immer wieder Vergrößern" nicht verzichten kann, muss ein anderer Speichermanager her. Ein einfacher, jedoch langsamer ist die nutzung von HeapAlloc, HeapFree und HeapRealloc, die man mit SetMemoryManager durch GetMem, FreeMem und ReallocMem aufrufen kann. Eine Kombination aus Delphi-Speichermanager und den HeapXxx API Funktionen brachte mir bis jetzt die besten Ergenisse, was Geschwindigkeit und Speicherverbrauch angeht.


Um es aber nicht nur auf Borland zu schieben: Auch der Speichermanager von C/C++ (malloc@msvcrtxx.dll) hat dieses Problem und der stammt von Microsoft.
  Mit Zitat antworten Zitat
Benutzerbild von mika
mika

Registriert seit: 25. Okt 2002
176 Beiträge
 
Delphi 6 Professional
 
#4

Array nacher wieder freigegeben

  Alt 14. Feb 2003, 17:11
Hallo an alle,

erstmal danke für die Antworten! Das mit dem beispiel von 4 und 120 MB
klingt echt interessant, ich probier das gleich mal aus! aber ich hatte
schon mal das problem wenn ich ein Dynamisches Array wieder freigeben will
das ich auf "einen Schlag" komplett reserviert hatte.

Ich probier das jetzt mal aus und melde mich heute abend wieder, wirklich
höchst interessant! Danke!


mdf, mika
:: don't Panic ::
  Mit Zitat antworten Zitat
janjan

Registriert seit: 16. Jan 2003
Ort: Bonn ("links über Königswinter ")
240 Beiträge
 
Delphi 4 Standard
 
#5
  Alt 14. Feb 2003, 18:34
Kuck mal hier, da gibts einen ersatz für den Memory Manager der angeblich um einiges besser arbeitet als das Original:

http://www.optimalcode.com/memmgr.htm

vielleicht bringts ja was...
  Mit Zitat antworten Zitat
jbg

Registriert seit: 12. Jun 2002
3.479 Beiträge
 
Delphi 10.1 Berlin Professional
 
#6
  Alt 14. Feb 2003, 19:09
Dieser ist besser. Nur stört mich daran eine Sache: Der belegte Speicher wird erst beim Programmende wieder freigegeben. Das ist nicht gerade performancesteifernd für andere Anwendungen und bekannlich ist Windows ein Multitasking Betriebsystem.
Wenn die Anwendung also für kurze Zeit 200 MB benötigt, dann bleiben diese 200 MB bis zum Programmende dem Programm zugeordnet und stehen nicht für andere Programme zur Verfügung.
  Mit Zitat antworten Zitat
Snoop007

Registriert seit: 15. Jan 2003
331 Beiträge
 
Delphi 6 Personal
 
#7
  Alt 14. Feb 2003, 22:12
mich interessiert dieses thema auch gerade
ich habe hier eine komponente geschrieben
http://www.delphipraxis.net/viewtopic.php?t=3205
die es ermöglicht, struckturierte dateien zu laden

das problem an der sache, nach dem laden der datei, verbraucht das programm mehr als das 100 fache von der eigendlichen grösse der zu lesenden datei

bsp. die datei ist 2,.. mb gross, der windowns taskmaneger zeigt mir 299,...kb an ...
  Mit Zitat antworten Zitat
jbg

Registriert seit: 12. Jun 2002
3.479 Beiträge
 
Delphi 10.1 Berlin Professional
 
#8
  Alt 14. Feb 2003, 22:48
Dabei handelt es sich um genau dasselbe Problem. Beim Hinzufügen vergrößerst du das Array immer um eins.

Wem der obige Speichermanager nicht behaart, da er den verwendeten Speicher nicht wieder freigibt, der kann meinen einsetzen. Dieser nutzt den vorhandenen Speichermanager und nach 10-maligem Aufruf von ReallocMem() für einen Speicherbereich wird der Speicher auf den ProcessHeap geschoben, der zwar beim reservieren langsamer als der von Delphi verwendete Speicher ist, aber eben nicht dieses Manko aufweist.
Angehängte Dateien
Dateityp: zip heapmemman.zip (1,1 KB, 24x aufgerufen)
  Mit Zitat antworten Zitat
Snoop007

Registriert seit: 15. Jan 2003
331 Beiträge
 
Delphi 6 Personal
 
#9
  Alt 14. Feb 2003, 23:10
das gucke ich mir mal an, danke
  Mit Zitat antworten Zitat
jbg

Registriert seit: 12. Jun 2002
3.479 Beiträge
 
Delphi 10.1 Berlin Professional
 
#10
  Alt 14. Feb 2003, 23:22
Bedenke, dass die Unit als allererste im Projektquellcode eingebunden wird.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2   

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:36 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