【发布时间】:2009-05-06 18:46:42
【问题描述】:
我正在尝试优化我的 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)
这样每个 Handler 都会对 List 进行不同的处理...
关于如何获得类的总大小,我使用了一个修改后的内存管理器,以便我可以跟踪“真正的”内存管理器为该类使用了多少内存。通过这种方式,我非常有信心实例不会被打包。
最后这是在 Delphi 7 中。我尝试使用 {$A1} 预编译器指令,但没有成功,字段以任何方式对齐,我可能有数百万个实例作为最坏的情况,因此节省 6 个字节可以保存几 MB 的结果。
【问题讨论】:
-
如果你把关键字“packed”放在class前面会发生什么? (看起来你已经忽略了那里的代码)
-
编译器错误:P 你可以使用打包的记录
-
您如何精确测量?看到我对该类的计算是字段的 6 个字节,并且打包确实对我有用,可能取决于编译器版本以及您是否正在为 .NET 编译?我的是 Delphi 2007,没有 .NET
-
我已经扩展了为什么我正在做我正在做的事情以及为什么打包记录不是一个选项。对不起,我第一次弄糊涂了。其中的数字只是一个例子来说明这一点,当然你必须考虑到虚拟方法表的空间以及类中存在的任何接口指针。
-
豪尔赫,你误会了。如果您将所有字段放入打包记录中,这并不妨碍您使用接口。编译器在定义类的布局时会自动为您处理接口字段。记录字段不会对此产生干扰。此外,接口字段不会影响对齐,因为它们无论如何都是四字节值。您也不需要特殊的内存管理器来衡量这一点;只需在类上使用 InstanceSize 函数即可。
标签: delphi optimization memory