Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Speicherplatz ermitteln: Objekt vs. Record (https://www.delphipraxis.net/148805-speicherplatz-ermitteln-objekt-vs-record.html)

s.h.a.r.k 8. Mär 2010 23:09


Speicherplatz ermitteln: Objekt vs. Record
 
Hallo,

wollte allgemein mal nachfragen, wie ich den genauen Speicherplatz von einer Instanz einer Klasse (samt darin gekapselten Objekten) und einem Record (samt darin gekapselten Objekten) ermitteln kann?

Und zwar komme ich auf diese Frage, da RTTI in D2010 leider ein Problem mit meinem Record hat und ich in der Zwischenzeit kurz davor bin auf ein Klasse umzusteigen. Ich finde das im Prinzip zwar erst mal totaler Overhead, aber da habe ich dann doch lieber einen gut lesbaren Code, aber etwas weniger Performance. So viel verkraftet der Benutzer dann doch noch :zwinker:

Wenn ihr mir im Speziellen noch helfen wollte:
Delphi-Quellcode:
// ----- Record -----
RInteger = record
private
  FValue : Variant; // Kann durch Setter nur NULL werden oder eine Zahl beinhalten
  procedure SetValue(const AVar: Variant);
public
  const VarType = varInteger;
  property Value : Variant read FValue write SetValue;
  function IsNull(): Boolean;
end;

// ----- In eine Klasse gefasst -----
RInteger = class(TObject)
private
  FValue : Variant; // Kann durch Setter nur NULL werden oder eine Zahl beinhalten
  procedure SetValue(const AVar: Variant);
public
  const VarType = varInteger;
  property Value : Variant read FValue write SetValue;
  function IsNull(): Boolean;
end;

hoika 9. Mär 2010 05:52

Re: Speicherplatz ermitteln: Objekt vs. Record
 
Hallo,

schnapp dir MemCheck oder FastMM4,
erzeuge die Klasse und den Record (New PRecord),
ohne sie wieder freizugeben.
Und schon zeigen dir beide Programme den exakten Speicherverbrauch an
(mem leak).


Heiko

olee 9. Mär 2010 08:38

Re: Speicherplatz ermitteln: Objekt vs. Record
 
Also mindestens sein Turbo Delphi ist das nicht nötig.

Es gibt eine globale Variable ReportMemoryLeaksOnShutdown
(könnte vllt. etwas anders heißen konnte ich grad nicht nachprüfen)

Setz die einfach beim Programmstart auf true und mach sonst soweit das gleiche was Hoika meinte.
(Instanz erzeugen und nicht freigeben)

Pass aber auf das nicht vorher schon irgendwelche mem-leaks da sind
(also vorher mal mit ReportMemoryLeaksOnShutdown = true ausführen, ohne die Instanz zu erzeugen)

Bei einer Klasse müsste auch InstanzeSize gehen (das klappt aber ja nicht, wenn du auch den Speicherverbrauch von Objekten, Strings usw. in der Klasse ermitteln willst)

Aber InstanzeSize (Klasse) und SizeOf (Record) kannst du für einen Vergleich nutzen, wenn beide den gleichen Inhalt haben.

MFG

xZise 9. Mär 2010 09:40

Re: Speicherplatz ermitteln: Objekt vs. Record
 
Moin,
was hältst du von einem PInteger?

Delphi-Quellcode:
RInteger = record
private
  FValue : PInteger;
public
  property Value : PInteger read FValue write FValue;
  function IsNull(): Boolean;
end;
MfG
Fabian

himitsu 9. Mär 2010 10:52

Re: Speicherplatz ermitteln: Objekt vs. Record
 
Delphi-Quellcode:
RInteger = {packed} record
private
  FValue : Integer;
  FNull : Boolean;
public
  procedure SetNull(yes : Boolean = true);
  property Value : PInteger read GetValue write SetValue;
  property IsNull : Boolean read FNull   write SetNull;
end;
Kleiner ist dagegen dann nur noch die Verwendung eines Wertes aus dem Wertebereich des Integers, welchen man dann als NULL ansieht.


Wenn man ein Objekt nur als Datenspeicher nutzt, dann ist der Record immer einen Hauch kleiner, da die Verwaltung des Objektes wegfällt.

Delphi-Quellcode:
type
  TRec = record
    a, b: Integer;
  end;
  TCls = class
    a, b: Integer;
  end;

ShowMessage(Format('%d %d', [SizeOf(TRec), TCls.InstanceSize]));
= 8 12

Die 4 zusätzlichen Byte sind die Referenz auf den Klassentypen,
dazu kommt dann noch ein bissl mehr an RTTI-Daten (ich denk mal, daß wird sich auch in der neuen RTTI nicht geändert haben).

Stevie 9. Mär 2010 11:46

Re: Speicherplatz ermitteln: Objekt vs. Record
 
Zitat:

Zitat von s.h.a.r.k
wollte allgemein mal nachfragen, wie ich den genauen Speicherplatz von einer Instanz einer Klasse (samt darin gekapselten Objekten) und einem Record (samt darin gekapselten Objekten) ermitteln kann?

Das geht imo nur durch rekursives Durchlaufen deiner Objekte/Records, da Objektreferenzen immer nur 4 Byte groß sind und TObject.InstanceSize dies auch nur berücksichtigt. D.h., wenn du in TMyObjekt1 ein weiteres TMyObjekt2 erzeugst und in einer FeldVariablen speicherst, wird die Größe nur um 4 Byte steigen (die Größe deiner FeldVariablen).
Das würde aber zu einigen Problemen führen:
- dass eine Objektinstanz von mehreren anderen Stellen aus referenziert wird. Wie ermittelst du dann den Speicherverbrauch deiner referenzierenden Objekte?
- dass Objektinstanzen sich gegenseitig referenzieren. Welche Instanz verbraucht dann Speicherplatz von welcher anderen?
Alles in allem keine einfache Angelegenheit.

s.h.a.r.k 9. Mär 2010 11:52

Re: Speicherplatz ermitteln: Objekt vs. Record
 
Okay, Prinzip verstanden :thumb: Ich müsste dann halt evtl. auch noch jedes Variable rekursiv durchgehen, wenn es sich denn um ein Objekt handelt.

Wobei es scheinbar doch nicht soo viel mehr an Overhead ist, wie ich anfangs befürchtet hatte :zwinker: Es enstehen halt geschätzt ~10000 Objekte anstatt Records (was zuvor einfach Variablen waren, aber durch das NULL-Mapping-Problem eben zu Records wurden).

Hier das was ich via der FastMM-Methoder herausgefunden habe:
Code:
Record:
20 Bytes
-> bei 10000 Objekten -> 200000 Bytes ->195 KB

Objekt:
28 Bytes
-> bei 10000 Objekten -> 280000 Bytes -> 273 KB

=> 40% mehr


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:35 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