为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C#
繁华开满天机 2019-08-27 10:42:42
在c#中以字节为单位查找对象实例的大小对于任何任意实例(不同对象,组合,单个对象等的集合)如何确定其大小(以字节为单位)?(我现在有各种对象的集合,我正在尝试确定它的聚合大小)编辑:有人写了一个可以做到这一点的对象的扩展方法吗?那个非常整洁的imo。
查看完整描述

3 回答

?
跃然一笑

TA贡献1826条经验 获得超6个赞

首先,一个警告:接下来的内容严格地说是丑陋的,无证件的黑客攻击。不要依赖于这项工作 - 即使它现在适用于您,它可能会在明天停止工作,任何次要或主要的.NET更新。

您可以使用本文中有关CLR内部MSDN杂志2005年5月的信息 - 深入了解.NET框架内部以了解CLR如何创建运行时对象 - 最后我检查过,它仍然适用。这是如何完成的(它通过TypeHandle类型检索内部“基本实例大小”字段)。

object obj = new List<int>(); // whatever you want to get the size ofRuntimeTypeHandle th = obj.GetType().TypeHandle;int size = *(*(int**)&th + 1);Console.WriteLine(size);

这适用于3.5 SP1 32位。我不确定64位上的字段大小是否相同 - 如果不是,则可能需要调整类型和/或偏移量。

这适用于所有“普通”类型,所有实例都具有相同的,定义良好的类型。那些不成对的是数组和字符串肯定,我也相信StringBuilder。对于它们,您将所有包含的元素的大小添加到它们的基本实例大小。


查看完整回答
反对 回复 2019-08-27
?
莫回无

TA贡献1865条经验 获得超7个赞

对于非托管类型,也就是值类型,结构:

        Marshal.SizeOf(object);

对于托管对象,我得到的更接近是近似值。

        long start_mem = GC.GetTotalMemory(true);

        aclass[] array = new aclass[1000000];
        for (int n = 0; n < 1000000; n++)
            array[n] = new aclass();

        double used_mem_median = (GC.GetTotalMemory(false) - start_mem)/1000000D;

不要使用序列化。二进制格式化程序会添加标题,因此您可以更改类并将旧的序列化文件加载到已修改的类中。

它也不会告诉你内存中的实际大小,也不会考虑内存对齐。

[编辑]通过在类的每个属性上递归使用BiteConverter.GetBytes(prop-value),您将获得以字节为单位的内容,这不计算类或引用的权重,但更接近现实。如果大小很重要,我建议使用字节数组进行数据和非托管代理类使用指针转换访问值,请注意这将是非对齐内存,因此在旧计算机上会很慢但是现代RAM上的巨大数据集将会是更快,因为最小化从RAM读取的大小将比未对齐更大的影响。


查看完整回答
反对 回复 2019-08-27
  • 3 回答
  • 0 关注
  • 609 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信