想知道这个,原因就一个:85000bytes以上的对象对于GC性能影响较大。我用sqlprofier监视过一些我们自己的biz entity,不过,runtime监视,不爽。。。

查了不少资料,李建忠老师的blog看了(问题出来了,还没有答案,期待ing...),google了一下:how to get a managed object size?找到了一个blog,在这里:http://blogs.msdn.com/cbrumme/archive/2003/04/15/51326.aspx

.net不提供SizeOf(manged obj)接口的原因我认为很简单,主要考虑alignment。
在看这个blog之前,我自己写了一段代码,也能大致的计算出来,不过我考虑得比较简单。
如何计算托管对象的大小// 销售订单,内嵌一个客户类
如何计算托管对象的大小
    public class BillOrder
    }

如何计算托管对象的大小// 客户,内嵌一个地址结构体
如何计算托管对象的大小
    public class Customer
    }

如何计算托管对象的大小// 地址结构体
如何计算托管对象的大小
    public struct Address
    }

生成一个销售订单对象
如何计算托管对象的大小BillOrder bo1 = new BillOrder(1000000);

好了,到此为止,我们要计算bo1的占用内存的大小。看我的第一个原始版本代码:
如何计算托管对象的大小// 对于nested对象,递归调用。
如何计算托管对象的大小
// 这里为了测试,只是简单的用了几个类型
如何计算托管对象的大小
        private static int Calc(object o)
        }

利用此方法,这么调用:
如何计算托管对象的大小int size = Calc(bo1);
得到的结果是:
Create a 1000000 bytes billorder
Create a 1000000 bytes billorder
bindata --- 1000000
num --- 4
Below is Customer
limit --- 4
name --- 7
Below is Address
end of Address(Total) --- 0
address --- 0
end of Customer(Total) --- 11
customer --- 0
id --- 4
1000019
就是说,这个对象大小,我这么粗略的计算,是1000019个字节。(上面没有考虑到字节对齐)

ok,其实上面那篇老外的blog,提到了一嘴,可以clone一个同样的object,然后计算两者指针的偏移。
然后看这段代码,我废了不少劲才写出来,如何计算托管对象的大小
如何计算托管对象的大小// 首先再new一个同样的销售订单出来
如何计算托管对象的大小
BillOrder bo1 = new BillOrder(1000000);
如何计算托管对象的大小BillOrder bo2 
= new BillOrder(1000000);
如何计算托管对象的大小
// 然后。。。
如何计算托管对象的大小
GCHandle h1  = GCHandle.Alloc(bo1);
如何计算托管对象的大小GCHandle h2 
= GCHandle.Alloc(bo2);
}

上面代码中,其实就是指针->指针->偏移+4这么一个转化。这个值,我是从debug-memory里面,“猜测”出来的,呵呵。没有仔细分析过clr header,所以我不知道它的原理。
好了,用上面的方法,我们得到的大小是:Size is:1000032。
我相信,这应该是一个中规中矩的销售订单的占用内存大小。

欢迎各位高手指教!

相关文章: