找出 .net 对象的大小

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/324053/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 10:41:44  来源:igfitidea点击:

Find out the size of a .net object

.netmemory-managementgarbage-collectionprofiling

提问by Matthew Steeples

I'm trying to find out how much memory my objects take to see how many of them are ending up on the Large Object Heap (which is anything over 85,000 bytes).

我试图找出我的对象占用了多少内存,以查看它们中有多少最终出现在大对象堆上(超过 85,000 字节)。

Is it as simple as adding 4 for an int, 8 for a long, 4 (or 8 if you're on 64 bit) for any reference types etc for each object, or are there overheads for methods, properties etc.

是否像为 int 添加 4,为 long 添加 8,为每个对象的任何引用类型等添加 4(或 8,如果您是 64 位)一样简单,或者是否存在方法、属性等的开销?

采纳答案by Jon Skeet

Don't forget that the size of an actual object doesn't include the size of any objects it references.

不要忘记实际对象的大小不包括它引用的任何对象的大小。

The only things which are likely to end up on the large object heap are arrays and strings - other objects tends to be relatively small in themselves. Even an object with (say) 10 reference type variables (4 bytes each on x86) and 10 GUIDs (16 bytes each) is only going to take up about 208 bytes (there's a bit of overhead for the type reference and sync block).

唯一可能出现在大对象堆上的东西是数组和字符串——其他对象本身往往相对较小。即使具有(例如)10 个引用类型变量(x86 上每个 4 个字节)和 10 个 GUID(每个 16 个字节)的对象也只会占用大约 208 个字节(类型引用和同步块有一些开销)。

Likewise when thinking about the size of an array, don't forget that if the element type is a reference type, then it's only the size of the referencesthat count for the array itself. In other words, even if you've got an array with 20,000 elements, the size of the array object itself will only be just over 80K (on x86) even if it references a lot more data.

同样,在考虑数组的大小时,不要忘记如果元素类型是引用类型,那么只有引用的大小才对数组本身计数。换句话说,即使你有一个包含 20,000 个元素的数组,数组对象本身的大小也只会超过 80K(在 x86 上),即使它引用了更多的数据。

回答by Gomes

Please follow these steps to get the size of the object.

请按照以下步骤获取对象的大小。

1) go to Visual Studio(2010) Project Properties - > Debug tab -> Enable unmanaged code debugging.

1) 转到 Visual Studio(2010) 项目属性 -> 调试选项卡 -> 启用非托管代码调试。

2) go to Visual Studio Debug menu -> Option and Settings -> Debugging -> Symbols.

2) 转到 Visual Studio 调试菜单 -> 选项和设置 -> 调试 -> 符号。

3) There enable Microsoft Symbol Server,leave the default.(symbols may start download)

3) 有启用微软符号服务器,保持默认。(符号可能会开始下载)

4) Set the break point in your code, start debugging(F5).

4)在你的代码中设置断点,开始调试(F5)。

5) Open Debug -> Windows -> Immediate Window.

5) 打开调试-> 窗口-> 立即窗口。

6) enter .load sos.dll(Son of Strike)

6) 输入.load sos.dll(Son of Strike)

7) enter !DumpHeap -type MyClass (the object you want to find size)

7)输入 !DumpHeap -type MyClass(你要查找的对象大小)

8) from the out put locate the address of the object i.e.(00a8197c)

8) 从输出中找到对象的地址 ie(00a8197c)

Address MT Size 00a8197c 00955124 36

地址 MT 大小 00a8197c 00955124 36

9) Next, !ObjSize 00a8197c

9) 接下来,!ObjSize 00a8197c

10) There you go -> sizeof(00a8197c) = 12 (0x48) bytes (MyClass)

10)你去 - > sizeof(00a8197c)= 12(0x48)字节(MyClass)

回答by serhio

If you can - Serialize it!

如果可以的话 - 序列化它!

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

回答by David Pokluda

You are getting into an area of advanced .NET debugging. Start with John Robins debugging books.

您将进入高级 .NET 调试领域。从John Robins 调试书籍开始

Use WinDBGwith Sos.dll (part of .NET distribution) and Sosex.dllextensions. With these tools you can really see what's happening when your application is running. You will find answers to your above mentioned questions.

WinDBG与 Sos.dll(.NET 发行版的一部分)和Sosex.dll扩展一起使用。使用这些工具,您可以真正了解应用程序运行时发生的情况。您将找到上述问题的答案。

(Another recommendation would be to install Shared Source CLI 2.0, aka. Rotor 2, to see what's going on under the hood.)

(另一个建议是安装Shared Source CLI 2.0,又名 Rotor 2,以查看引擎盖下发生了什么。)

回答by IvanH

Gomes's method simplified:

Gomes的方法简化了:

  1. go to Visual Studio(2010) Project Properties - > Debug tab -> Enable unmanaged code debugging.

  2. Set the break point in your code, start debugging(F5).

  3. Open Debug -> Windows -> Immediate Window.

  4. enter .load sos

  5. enter (replace myObject with the name of your object)

  1. 转到 Visual Studio(2010) 项目属性 -> 调试选项卡 -> 启用非托管代码调试。

  2. 在代码中设置断点,开始调试(F5)。

  3. 打开调试 -> Windows -> 立即窗口。

  4. 输入 .load sos

  5. 输入(将 myObject 替换为您的对象名称)

? String.Format("{0:x}",Integer.Parse(System.Runtime.InteropServices.GCHandle.InternalAddrOfPinnedObject(System.Runtime.InteropServices.GCHandle.Alloc(myObject).GetHandleValue()).ToString()) - 4)

? String.Format("{0:x}",Integer.Parse(System.Runtime.InteropServices.GCHandle.InternalAddrOfPinnedObject(System.Runtime.InteropServices.GCHandle.Alloc( myObject).GetHandleValue()).ToString()) - 4 )

   6. Use result as parameter of !ObjSize

   6. 使用结果作为 !ObjSize 的参数

see: SOS.DLL, object Address and Visual Studio debugger Introduction

参见:SOS.DLL、对象地址和Visual Studio调试器介绍

Example (we are looking for object named tbl):

示例(我们正在寻找名为 的对象tbl):

.load sos
extension C:\Windows\Microsoft.NET\Framework\v4.0.30319\sos.dll loaded
? string.Format("{0:x}",Integer.Parse(System.Runtime.InteropServices.GCHandle.InternalAddrOfPinnedObject(System.Runtime.InteropServices.GCHandle.Alloc(tbl).GetHandleValue()).ToString())-4)
"27ccb18"
!ObjSize 27ccb18
PDB symbol for clr.dll not loaded
sizeof(027ccb18) =       154504 (     0x25b88) bytes (System.Data.DataTable)

回答by Barry Kelly

Unless it's a huge valuetype or instance type (i.e. many thousands of fields), the only types you need to worry about are large arrays, or strings. Of course, to figure out the size of an array, you need to know the element size.

除非它是一个巨大的值类型或实例类型(即数千个字段),否则您唯一需要担心的类型是大型数组或字符串。当然,要计算数组的大小,您需要知道元素大小。

.NET (currently) aligns types in much the same way that native compilers align types. Fundamental types have natural alignments that are usually the rounded-up integral power of two closest to their size:

.NET(当前)对齐类型的方式与本机编译器对齐类型的方式大致相同。基本类型具有自然对齐,通常是最接近其大小的两个整数幂的四舍五入:

Single, Int32, UInt32 - 4
IntPtr, UIntPtr, pointers, references  - 4 on 32-bit, 8 on 64-bit
Double, Int64, UInt64 - 8
Char, Int16, UInt16   - 2
Byte, SByte           - 1

When assembling a type, the compiler will make sure that all fields of any given type have their starting offset within the instance aligned to a boundary that matches that type - assuming that explicit layout isn't being used.

组装类型时,编译器将确保任何给定类型的所有字段在实例内的起始偏移量与匹配该类型的边界对齐 - 假设未使用显式布局。

User-defined types themselves have an alignment, which is calculated as the highest alignment of any of their field types. The type's size is extended if necessary to make the size of the type aligned too.

用户定义的类型本身有一个对齐方式,它被计算为其任何字段类型的最高对齐方式。如有必要,可以扩展类型的大小以使类型的大小也对齐。

But of course, all reference types are still only IntPtr.Size in size and alignment, so the size of reference type will not affect arrays of that type.

但是当然,所有引用类型在大小和对齐方式上仍然只有 IntPtr.Size,所以引用类型的大小不会影响该类型的数组。

Note that the CLR may choose, at its discretion, to layout types differently than described above, maybe to increase cache locality or reduce padding required by alignment.

请注意,CLR 可能会自行选择与上述不同的布局类型,可能会增加缓存局部性或减少对齐所需的填充。

回答by Patrick Artner

As an estimate (in 2017) you can debug into your application, set a breakpoint before your dictionary comes to live, take a "Memory Usage Snapshot" (Tab: Memory Usage under Diagnostic Tools) , fill your dictionary and get another snapshot - not exact put a good gestimate.

作为估计(在 2017 年),您可以调试到您的应用程序,在您的字典上线之前设置断点,拍摄“内存使用情况快照”(标签:诊断工具下的内存使用情况),填写您的字典并获取另一个快照 - 不是确切地说是一个很好的估计。