猿问

在c#中以字节为单位查找对象实例的大小

在c#中以字节为单位查找对象实例的大小

对于任何任意实例(不同对象,组合,单个对象等的集合)

如何确定其大小(以字节为单位)?

(我现在有各种对象的集合,我正在尝试确定它的聚合大小)

编辑:有人写了一个可以做到这一点的对象的扩展方法吗?那个非常整洁的imo。


繁华开满天机
浏览 610回答 3
3回答

跃然一笑

首先,一个警告:接下来的内容严格地说是丑陋的,无证件的黑客攻击。不要依赖于这项工作 - 即使它现在适用于您,它可能会在明天停止工作,任何次要或主要的.NET更新。您可以使用本文中有关CLR内部MSDN杂志2005年5月的信息 - 深入了解.NET框架内部以了解CLR如何创建运行时对象&nbsp;- 最后我检查过,它仍然适用。这是如何完成的(它通过TypeHandle类型检索内部“基本实例大小”字段)。object&nbsp;obj&nbsp;=&nbsp;new&nbsp;List<int>();&nbsp;//&nbsp;whatever&nbsp;you&nbsp;want&nbsp;to&nbsp;get&nbsp;the&nbsp;size&nbsp;ofRuntimeTypeHandle&nbsp;th&nbsp;=&nbsp;obj.GetType().TypeHandle;int&nbsp;size&nbsp;=&nbsp;*(*(int**)&th&nbsp;+&nbsp;1);Console.WriteLine(size);这适用于3.5 SP1 32位。我不确定64位上的字段大小是否相同 - 如果不是,则可能需要调整类型和/或偏移量。这适用于所有“普通”类型,所有实例都具有相同的,定义良好的类型。那些不成对的是数组和字符串肯定,我也相信StringBuilder。对于它们,您将所有包含的元素的大小添加到它们的基本实例大小。

莫回无

对于非托管类型,也就是值类型,结构:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Marshal.SizeOf(object);对于托管对象,我得到的更接近是近似值。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;long&nbsp;start_mem&nbsp;=&nbsp;GC.GetTotalMemory(true); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;aclass[]&nbsp;array&nbsp;=&nbsp;new&nbsp;aclass[1000000]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(int&nbsp;n&nbsp;=&nbsp;0;&nbsp;n&nbsp;<&nbsp;1000000;&nbsp;n++) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;array[n]&nbsp;=&nbsp;new&nbsp;aclass(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;double&nbsp;used_mem_median&nbsp;=&nbsp;(GC.GetTotalMemory(false)&nbsp;-&nbsp;start_mem)/1000000D;不要使用序列化。二进制格式化程序会添加标题,因此您可以更改类并将旧的序列化文件加载到已修改的类中。它也不会告诉你内存中的实际大小,也不会考虑内存对齐。[编辑]通过在类的每个属性上递归使用BiteConverter.GetBytes(prop-value),您将获得以字节为单位的内容,这不计算类或引用的权重,但更接近现实。如果大小很重要,我建议使用字节数组进行数据和非托管代理类使用指针转换访问值,请注意这将是非对齐内存,因此在旧计算机上会很慢但是现代RAM上的巨大数据集将会是更快,因为最小化从RAM读取的大小将比未对齐更大的影响。
随时随地看视频慕课网APP
我要回答