【问题标题】:How to calculate delphi class size using TMemoryStream.size?如何使用 TMemoryStream.size 计算 delphi 类大小?
【发布时间】:2020-12-06 18:26:58
【问题描述】:

我正在尝试查找示例 TControl、TWinControl 等的内置类的大小。尝试使用 InstanceSize(),这反过来可能不会增加少数类型的大小,将它们视为引用。

找到一个有趣的堆栈溢出线程,讨论 TMemoryStream 以找出类大小:Getting the Size of a Class or Object in the same format as a File Size? 无法获得有关如何使用 TMemoryStream 来确定类大小的太多信息,我可以寻求帮助吗?

【问题讨论】:

    标签: delphi delphi-10.4-sydney


    【解决方案1】:

    你是对的:TObject.InstanceSize 返回内存中的实例大小。不是嵌套字段。

    如果您想计算类实例在内存中的“大小”,那么该值将永远不会与任何流式处理过程相匹配。

    我的意思是,如果您将class 实例序列化为TStream,则大小将取决于实际的序列化。不是使用的总内存大小。大多数序列化引擎只会序列化已发布的属性,而不是公共的和嵌套的受保护字段。如果您序列化为 JSON、DFM 二进制、DFM 文本、ProtoBuf 或我们的 mORMot 二进制布局,您将获得不同的值,这与实际的 RAM 消耗不匹配。

    对于嵌套引用类型,例如string 或动态数组,这种情况甚至是值得的。他们使用引用计数,因此单个string 实例,如果在多个属性/变量中重用,只会在所有出现时消耗一次它的长度......那么嵌套对象呢,这可能是在实例之间重用?

    所以没有简单的方法来计算class 实例消耗多少“内存”。您可以做的是编写自己的函数,并对消耗的内存进行“估计”。类似的东西

     function TMyObject.ConsumedBytes: integer;
     begin
       result := InstanceSize +
         length(fName) * SizeOf(char) +
         length(fFirstName) * SizeOf(char) +
         length(fAddress) * SizeOf(char);
     end;
    

    即使这也将被视为一种估计,而不是消耗了多少 RAM。例如,像string 这样的某些类型确实在文本之前有一个标题(包括长度、引用计数和代码页),并且内存管理器本身总是会保留比实际需要的多一点的空间,这是为了优化的低级原因。

    我想你需要完善你的目标。如果要检查内存使用情况,那么您需要了解一下 Delphi 如何将其内存用于其低级类型,以及堆内存管理器如何从操作系统中保留内存区域。

    【讨论】:

    • 这是正确的答案。但是您需要将字符串长度乘以SizeOf(Char)
    • @AndreasRejbrand 你是对的:我已经修好了。
    • 感谢@ArnaudBouchez,我来自 C++ 背景,对 Delphi 有点新意。如果 InstanceSize 可以做 sizeof 在 C/C++ 中所做的事情,那就绰绰有余了。虽然我已经制作了与返回的 InstanceSize 匹配的结构,但应用程序仍然对大小不满意。
    • 技术上应该是(Length + 1)*SizeOf(Char) + StringHeaderSize。 StringHeaderSize 对于 32 位应用程序是 12 个字节,对于 64 位应用程序是 16 个字节(截至西雅图)。 Codepage(2) + SizeofElement(2) + RefCount(4) + Length(4) + (64bitsonly)padding(4)。 Length+1 是因为字符串始终保留(至少)1 个附加字符,并将其设为 null 以实现 PChar 兼容性。
    • 虽然你在原则上是对的,@KenBourassa,但我们基本上仍然只是做一个估计,所以它可能“足够好”。如果你想“精确”,你首先需要更精确地定义数字应该是什么,然后你需要一个相当复杂的实现。例如,您必须检查两个字符串字段是否指向同一个堆对象。
    猜你喜欢
    • 1970-01-01
    • 2019-08-22
    • 1970-01-01
    • 1970-01-01
    • 2018-07-10
    • 2019-03-17
    • 2015-09-05
    • 1970-01-01
    • 2020-09-02
    相关资源
    最近更新 更多