C#中如何获取对象实例大小?

yangfan369 2008-07-10 02:29:23
如题,在一个类中定义如下:
Class Test
{
public string s;
public int[] ints;
}
其中ints维数是动态的,请问如何获取Test的一个实例的大小?
...全文
2357 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
outman_sole 2010-06-02
  • 打赏
  • 举报
回复
序列化,计算字节数
fuadam 2008-07-10
  • 打赏
  • 举报
回复
晕了,!clrstack -a 竟然看不到List<int>的地址
fuadam 2008-07-10
  • 打赏
  • 举报
回复
也就是说当调用List的Remove方法后,List所引用的数据还是会回到gc堆的,如果从这个角度来说.net本身没法做cache因为,cache就是开辟一块内存然后实现LRU算法的,但是我们无法把一堆数据固定在LOH或者GCH里,那么还是去用memcache这种第三方组件吧
gomoku 2008-07-10
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 fuadam 的回复:]
to gomoku:
list在扩大的时候是否要进入LOH呢?
[/Quote]

list本身始终在GC中,但list的数据有可能到LOH去。
看清楚了(输入有删节):


static void Main(string[] args)
{
List<int> list = new List<int>(80000/4);
for (int i = 0; i < 80000 / 4; i++) l.Add(3);

object o = list;

// break point 1
list.AddRange(list);

// break point 2
}


!clrstack -a
LOCALS:
<CLR reg> = 0x01e61c58

!dumpobj 0x01e61c58 // at break point 1
Name: System.Collections.Generic.List`1[[System.Int32, mscorlib]]

MT Field Offset Type VT Attr Value Name
7912d7c0 40009c7 4 System.Int32[] 0 instance 01e61c70 _items <----1 in GC generation 2
79102290 40009c8 c System.Int32 1 instance 20000 _size
79102290 40009c9 10 System.Int32 1 instance 20000 _version
790fd0f0 40009ca 8 System.Object 0 instance 00000000 _syncRoot
7912d7c0 40009cb 0 System.Int32[] 0 shared static _emptyArray


!dumpobj 0x01e61c58 // at break point 2
Name: System.Collections.Generic.List`1[[System.Int32, mscorlib]]

MT Field Offset Type VT Attr Value Name
7912d7c0 40009c7 4 System.Int32[] 0 instance 02e63030 _items <----2 in Large Object heap
79102290 40009c8 c System.Int32 1 instance 40000 _size
79102290 40009c9 10 System.Int32 1 instance 20001 _version
790fd0f0 40009ca 8 System.Object 0 instance 00000000 _syncRoot
7912d7c0 40009cb 0 System.Int32[] 0 shared static _emptyArray


!eeheap
=======================================
Number of GC Heaps: 1
generation 0 starts at 0x01e61018
generation 1 starts at 0x01e6100c
generation 2 starts at 0x01e61000 <------1
Large object heap starts at 0x02e61000 <------2
fuadam 2008-07-10
  • 打赏
  • 举报
回复
to gomoku:
list在扩大的时候是否要进入LOH呢?
gomoku 2008-07-10
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 fuadam 的回复:]
为什么要做cache就是大对象或者创建起来非常耗时的数据要放到cache里,那么机会有这个问题1个size大于85K的List是要进入LOH的,如果通过Remove方法List对象的size小于85K了,是不是要被放入gc堆中
[/Quote]

1、如果要做cache可以用WeakReference。
2、List对象的Add(或者Remove)并不是真正的动态扩展(缩小)原有内存,而是创建新的对象,拷贝数据,删除旧对象。比如下面的伪码:

class List
{
int length;
int capacity = 8;
int[] buf = new int[8];

public void Add(int val)
{
if( length == capacity - 1 )
{
capacity *= 2; // 数组扩大一倍
int[] newBuf = new int[ capacity ]; // 创建新对象
Array.Copy(newBuf, buf, length); // 拷贝数据
buf = newBuf; // 删除旧对象
}
buf[length++] = val;
}
}

xdp4507 2008-07-10
  • 打赏
  • 举报
回复
学习了,谢谢同志们!~
江城老温 2008-07-10
  • 打赏
  • 举报
回复
[Quote=引用楼主 yangfan369 的帖子:]
如题,在一个类中定义如下:
Class Test
{
public string s;
public int[] ints;
}
其中ints维数是动态的,请问如何获取Test的一个实例的大小?
[/Quote]

ints的维数?你是说长度是动态吧?如果是长度,那么你是无法实现的。

实例大小,假如你如下实例:

Test t = new Test();
t.s = "a";
t.ints = int[6];//notes,u must set the index here.

那么你可以得到t的大小:
t.s.Length + t.ints.Length

这样得到的是字节数。
fuadam 2008-07-10
  • 打赏
  • 举报
回复
为什么要做cache就是大对象或者创建起来非常耗时的数据要放到cache里,那么机会有这个问题1个size大于85K的List是要进入LOH的,如果通过Remove方法List对象的size小于85K了,是不是要被放入gc堆中
gomoku 2008-07-10
  • 打赏
  • 举报
回复
1、关于大对象。.Net是用大对象托管堆(Large Object Heap)来管理大对象的(目前大于85000字节算大对象)。目前大对象堆并不移动对象(性能考虑)。
2、Class Test不一定是连续的。Test的实例包含着两个引用,一个引用指向托管堆中的一个字符串对象,一个引用指向托管堆中的一个数组对象。
3、即使你得到Test的实例总占用内存的大小,你也没有办法有效的管理他们。硬性管理他们只会降低CLR的性能。
4、如果你只是大体估算程序的内存占用,则用常识(比如int-4字节,double-8字节,char-2字节)就可以了。至于管理开销(目前每个对象8个字节),则不需要考虑。

stning 2008-07-10
  • 打赏
  • 举报
回复
楼主查看一下il代码
fuadam 2008-07-10
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 yangfan369 的回复:]
实例的大小就是指:
Test t=new Test();
t.s="fasf";
t.ints=new int[10];
t就是Test一个实例啊,现在想知道t在内存中的大小。

我本意想做一个缓存管理器,然后对缓存池的大小进行控制;但是首先对于需要保存到缓存的对象实例大小必须得到才行。
[/Quote]
我也有这种想法,解决实例的大小只是初步的,怎么处理大对象才是麻烦的
yangfan369 2008-07-10
  • 打赏
  • 举报
回复
实例的大小就是指:
Test t=new Test();
t.s="fasf";
t.ints=new int[10];
t就是Test一个实例啊,现在想知道t在内存中的大小。

我本意想做一个缓存管理器,然后对缓存池的大小进行控制;但是首先对于需要保存到缓存的对象实例大小必须得到才行。
gomoku 2008-07-10
  • 打赏
  • 举报
回复

如题,在一个类中定义如下:
Class Test
{
public string s;
public int[] ints;
}
其中ints维数是动态的,请问如何获取Test的一个实例的大小?


什么是"实例的大小"?
或者讲一下你的目的?
fuadam 2008-07-10
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 pupo 的回复:]
Marshal.SizeOf 方法

返回类的非托管大小(以字节为单位)。
[/Quote]
Marshal.SizeOf 对class类型无效,只能计算struct
fuadam 2008-07-10
  • 打赏
  • 举报
回复
array本身字段大小是12,10个int类型就是40 所以 ints = 52
string本书字段大小是18,2个char类型是4 所以 s = 22但由于4字节对齐所以是24
Test本身是 syncidx + methodtype + s + ints = 4 + 4 + 4 + 4 = 16

所以t的实际大小是 16 + 24 + 52 = 92
pupo 2008-07-10
  • 打赏
  • 举报
回复
Marshal.SizeOf 方法

返回类的非托管大小(以字节为单位)。
zzyhuian06142 2008-07-10
  • 打赏
  • 举报
回复
把ints直接定义成Static算了,调用直接Test.ints.length
yangfan369 2008-07-10
  • 打赏
  • 举报
回复
我想知道
Test t=new Test();
t.s="aa";
t.ints=new int[10];
其中t占的内存空间有多大?不知道能否实现?sizeof是不行了。
ericzhangbo1982111 2008-07-10
  • 打赏
  • 举报
回复
Class Test
{
public string s;
public int[] ints;
}


Test t=new Test();
t.s="aa";
t.ints=new int[10];
你只是定义了,并没有分配它有多大

110,538

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧