在Delphi中优化班级大小.是否有类似“包装类"的东西? [英] Optimizing Class Size in Delphi. Is there something like "packed classes"?

查看:46
本文介绍了在Delphi中优化班级大小.是否有类似“包装类"的东西?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试优化我的Delphi类的大小,以使它们占用的内存尽可能少,因为我创建了大量此类.

问题是,类本身很小,但没有占用我期望的空间.例如,如果我有

type MyClass = class
  private
    mMember1 : integer;
    mMember2 : boolean;
    mMember3 : byte;
end;

我希望它使用6个字节,但是由于对齐,它最终使用12个字节,因此布尔型使用4个字节而不是1个字节...字节字段也是如此...

对于记录,您可以使用{$ A1}指令,也可以将其声明为打包记录以使其仅占用所需的内存.

有什么办法可以让类做同样的事情吗? (也许是有关如何正确重写NewInstance类方法的一些教程?)

好的,关于我在做什么的一些解释...

首先,实际类的大小约为40个字节,其中包括VMT和接口指针占用的空间.

所有类都继承自基本的RefCounting类,该类的大小为8个字节(整数FRefCount和一些允许引用计数的方法),并且必须支持接口(因此根本不使用打包记录).

此对象被传递并被转换为几样东西,而处理程序却不知道它们得到了什么.例如,我有一个可以接收TItems列表的类,并且执行以下操作:

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.

解决方案

您可以将打包记录用作对象字段:

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;

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;

这篇关于在Delphi中优化班级大小.是否有类似“包装类"的东西?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆