Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Optimizing Class Size in Delphi. Is there something like "packed classes"?

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.

like image 751
Jorge Córdoba Avatar asked May 06 '09 18:05

Jorge Córdoba


1 Answers

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;
like image 108
Gerry Coll Avatar answered Nov 15 '22 12:11

Gerry Coll