我试图优化我的Delphi类的大小,以便尽可能少地占用内存,因为我创建了大量的内存。
事情是,这些课本身很小,但他们没有占用我期待的空间。 例如,如果我有
type MyClass = class private mMember1 : integer; mMember2 : boolean; mMember3 : byte; end;我期望它使用6个字节,但由于对齐最终使用了12个字节,这就是布尔值使用了4个字节而不是1个字节......并且字节字段也是这样。
对于记录,您可以使用{$ A1}指令或将其声明为打包记录,以便仅用尽所需内存。
有什么办法可以用类来做同样的事情吗? (也许一些关于如何正确覆盖NewInstance类方法的教程?)
编辑:好的,关于我在做什么的一点解释...
首先,实际的类大小是40字节,包括VMT和接口指针占用的空间。
这些类都从一个大小为8字节的基本RefCounting类(一个整数FRefCount和一些允许引用计数的方法)继承,它们必须支持接口(因此根本不使用打包记录)。
这些对象会被传递并被转换成几件事情,而处理者不知道他们得到了什么。 例如,我有一个接收TItem列表的类,并执行如下操作:
if Supports(List[i], IValuable, IValInstance) then Eval(IValInstance.Value);那么另一个处理程序可能检查其他接口
If Supports(List[i], IStringObject, IStringInstance) then Compose(IStringInstance.Value)这样,每个处理程序的列表得到不同的处理...
关于我如何获得班级的总大小,我正在使用修改的内存管理器,以便我可以跟踪“真实”内存管理器为班级使用的内存量。 就这样,我非常自信的实例没有被打包。
最后,这是在Delphi 7中。我尝试过使用{$ A1}预编译器指令,但没有任何运气,字段以任何方式对齐,并且我可能有几百万个实例作为最坏情况,因此保存6个字节可能导致多个MB正在保存。
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.
最满意答案
您可以使用打包记录作为对象的字段:
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;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;更多推荐
发布评论