对于引用类型,是否有类似于sizeof()的等效函数?

21

我正在寻找一种获取引用类型实例大小的方法。sizeof仅适用于值类型。这可行吗?


这不是问题,只是一个好奇的练习。在请求期间,我有一堆项目放入HttpContext.Items中,我只是好奇它们占用了多少内存(即使它并不重要)。我正在经历一个“测量一切”的阶段。 - John Sheehan
有其他方法可以确定这一点(无需修改代码)。只需使用内存分析器即可。任何体面的分析器都会显示每个特定实例分配的字节数,以及实例持有的所有内存,包括被引用实例占用的内存。 - Marek
6个回答

12
您需要使用Marshal.SizeOf编辑:这是用于不安全代码的,但同样适用于sizeof()。

4
Marshal.SizeOf可能返回的字节数与所使用的数字不同。 - Thomas Bratt

10
如果您可以接受比完美略逊一筹的准确度,并且为了比较而言,您可以序列化对象并测量其大小(例如以字节为单位)。
编辑:因为它比valuetype的sizeof要复杂一些,例如:引用类型可以具有对其他对象的引用等等......我不知道有没有精确且简单的方法来做到这一点...

4
最近我有一个类似的问题,想知道在C#中Object和LinkedListNode的大小。为了解决这个问题,我开发了一个程序,它会执行以下操作:
  1. 测量程序的“工作集”
  2. 分配大量对象。
  3. 再次测量“工作集”。
  4. 将差异除以分配的对象数。
在我的电脑上(64位),我得到了以下数据:
Measuring Object:
iter    working set     size estimate
-1      11190272
1000000 85995520        74.805248
2000000 159186944       73.998336
3000000 231473152       73.4276266666667
4000000 306401280       73.802752
5000000 379092992       73.580544
6000000 451387392       73.3661866666667
7000000 524378112       73.3125485714286
8000000 600096768       73.613312
9000000 676405248       73.9127751111111
Average size: 73.7577032239859
Measuring LinkedListNode<Object>:
iter    working set     size estimate
-1      34168832
1000000 147959808       113.790976
2000000 268963840       117.397504
3000000 387796992       117.876053333333
4000000 507973632       118.4512
5000000 628379648       118.8421632
6000000 748834816       119.110997333333
7000000 869265408       119.299510857143
8000000 993509376       119.917568
9000000 1114038272      119.985493333333
Average size: 118.296829561905
Estimated Object size: 29.218576886067
Estimated LinkedListNode<reference type> size: 44.5391263379189

根据数据显示,分配数百万个对象的平均大小约为29.2字节。LinkedListNode对象约为44.5字节。这个数据说明了两件事情:

  1. 系统很少会分配部分字节。小数点后面的字节表示CLR为了分配和跟踪数百万个引用类型所需的开销。
  2. 如果我们简单地向下取整字节数,对于引用类型而言可能仍然无法获得正确的字节数。这可以从对象的度量中清楚地看出。如果我们向下取整,假设大小为29字节,理论上是可能的,但由于填充而不太可能。为了提高性能,对象分配通常需要进行填充以实现对齐。我猜测CLR对象将是4字节对齐的。

假设CLR开销和4字节对齐,我估计C#中一个Object的大小为28字节,LinkedListNode为44字节。

顺便说一下,Jon Skeet在我之前就想到这种方法,并在这个答案中回答了类似的问题。


1
如果可以的話,請把它序列化!
Dim myObjectSize As Long

Dim ms As New IO.MemoryStream
Dim bf As New Runtime.Serialization.Formatters.Binary.BinaryFormatter()
bf.Serialize(ms, myObject)
myObjectSize = ms.Position

1

请注意,Marshal.SizeOf是用于不安全代码的...

我认为对于托管代码来说这是不可能的,也许您可以解释一下您的问题,可能有其他解决方法。


1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接