1

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

发现一个有趣的堆栈溢出线程谈论 TMemoryStream 以找出类大小:Getting the Size of a Class or Object in the same format as a File Size? 无法获得有关如何使用 TMemoryStream 来计算班级规模的太多信息,我可以获得有关此方面的帮助吗?

4

1 回答 1

5

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

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

我的意思是,如果您将 class 实例序列化为 a 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 如何将其内存用于其低级类型,以及堆内存管理器如何从操作系统中保留内存区域。

于 2020-12-06T20:53:06.010 回答