I'm trying to optimize the size of my Delphi classes so that they take up as less memory as possible cause I'm creating a great number of them.
The thing is, the classes themselves are pretty small but they aren't taking the space I was expecting. For example if I have
type MyClass = class
private
mMember1 : integer;
mMember2 : boolean;
mMember3 : byte;
end;
I will expect it to use 6 bytes, but, due to alignment it ends up using 12 bytes, that's booleans use up 4 bytes instead of 1 byte... and the same goes for the byte field...
For records you can either use the {$A1} directive or declare it as a packed record to make it use up just the needed memory.
Is there any way to make the same thing with classes? (Maybe some tutorial on how to correctly override NewInstance class method?)
Edit: Ok, a little explanation about what I'm doing...
First, real class size is something like 40 bytes including the space taken up by the VMT and the Interface pointers.
The classes all inherit from a base RefCounting class whose size is 8 bytes (an integer FRefCount and some methods to allow reference counting) and they MUST support interfaces (hence not using packed records at all).
This objects get passed around and being casts to several things, whithout the handlers knowing what they got. For example, I've got a class that receives a List of TItems and does something like:
if Supports(List[i], IValuable, IValInstance) then
Eval(IValInstance.Value);
then another handler may check for other interface
If Supports(List[i], IStringObject, IStringInstance) then
Compose(IStringInstance.Value)
That way the List gets treated different by each Handler...
About how I get the total size of the class I'm using a modified Memory Manager so that I can keep track of how much memory the "real" memory manager uses up for the class. In that way I'm pretty confident instances are not being packed.
Finally this is in Delphi 7. I've tried to use the {$A1} precompiler directive with no luck, fields get aligned any way, and I may have several million instances as a worst case scenario so saving 6 bytes can result on several MB being saved.
You could use a packed record as a field of your objects:
type
TMyRecord = packed record
Member1 : integer;
Member2 : boolean;
Member3 : byte;
end;
TMyClass = class
private
FData : TMyRecord;
function GetMember1 : Integer;
public
property Member1 : Integer read GetMember1;
// Later versions of Delphi allow "read FData.Member1;", not sure when from
end;
function TMyClass.GetMember1 : integer;
begin
result := FData.Member1;
end;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With