我试图找出我的对象占用了多少内存来查看其中有多少最终出现在 大型对象堆(超过 85,000 字节的任何内容)。
是不是像为每个对象添加 4(表示 int)、添加 8(表示 long)、添加 4(如果是 64 位,则添加 8)作为任何引用类型等那么简单,还是有方法、属性等的开销?
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).
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.?
发布评论
评论(8)
不要忘记,实际对象的大小不包括它引用的任何对象的大小。
唯一可能最终出现在大型对象堆上的东西是数组和字符串 - 其他对象本身往往相对较小。 即使一个对象具有(比如说)10 个引用类型变量(在 x86 上每个 4 字节)和 10 个 GUID(每个 16 字节)也只会占用大约 208 个字节(类型引用和同步块有一些开销)。
同样,在考虑数组的大小时,不要忘记,如果元素类型是引用类型,那么只有引用的大小才算作数组本身。 换句话说,即使你有一个包含 20,000 个元素的数组,即使它引用了更多的数据,数组对象本身的大小也只会超过 80K(在 x86 上)。
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).
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 references that 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.
请按照以下步骤获取物体的尺寸。
转到 Visual Studio 2010 项目属性 → 调试选项卡 → 启用非托管代码调试。
转到 Visual Studio“调试”菜单→“选项和设置”→“调试”→“符号”。
在那里,启用 Microsoft Symbol Server 并保留默认值(符号可能会开始下载)。
在代码中设置断点,开始调试 (F5)。
打开调试→Windows→立即窗口。
输入
.load sos.dll
(Son of Strike)输入
!DumpHeap -type MyClass
(你要查找大小的对象的)从输出中找到该对象的地址,即(00a8197c)
地址 MT 大小
00a8197c 00955124 36
下一步,
!ObjSize 00a8197c
就是这样 → sizeof(00a8197c) = 12 (0x48) 字节 (MyClass)
Please follow these steps to get the size of the object.
Go to Visual Studio 2010 Project Properties → Debug tab → Enable unmanaged code debugging.
Go to the Visual Studio Debug menu → Options and Settings → Debugging → Symbols.
There, enable Microsoft Symbol Server and leave the default (symbols may start a download).
Set the breakpoint in your code, start debugging (F5).
Open Debug → Windows → Immediate Window.
Enter
.load sos.dll
(Son of Strike)Enter
!DumpHeap -type MyClass
(the object you want to find the size of)From the output, locate the address of the object, i.e. (00a8197c)
Address MT Size
00a8197c 00955124 36
Next,
!ObjSize 00a8197c
There you go → sizeof(00a8197c) = 12 (0x48) bytes (MyClass)
如果可以的话 - 将其序列化!
If you can - Serialize it!
您正在进入高级 .NET 调试领域。 从 John Robins 调试书籍开始。
将 WinDBG 与 Sos.dll(.NET 发行版的一部分)和 < a href="http://www.stevestechspot.com/SOSEXANewDebuggingExtensionForManagedCode.aspx" rel="noreferrer">Sosex.dll 扩展。 使用这些工具,您可以真正了解应用程序运行时发生的情况。 您将找到上述问题的答案。
(另一个建议是安装 共享源 CLI 2.0,又名 Rotor 2,了解幕后情况。)
You are getting into an area of advanced .NET debugging. Start with John Robins debugging books.
Use WinDBG with Sos.dll (part of .NET distribution) and Sosex.dll extensions. With these tools you can really see what's happening when your application is running. You will find answers to your above mentioned questions.
(Another recommendation would be to install Shared Source CLI 2.0, aka. Rotor 2, to see what's going on under the hood.)
戈麦斯的方法简化:
Go到 Visual Studio (2010) 项目属性* → 调试选项卡 → 启用非托管代码调试。
在代码中设置断点,开始调试 (F5)。
打开调试→Windows→立即窗口。
输入
.load sos
输入(将 myObject 替换为您的对象的名称)
<块引用>
?
String.Format("{0:x}",Integer.Parse(System.Runtime.InteropServices.GCHandle.InternalAddrOfPinnedObject(System.Runtime.InteropServices.GCHandle.Alloc(myObject).GetHandleValue()) .ToString())
将结果作为
!ObjSize
的参数参见:SOS.DLL、对象地址和 Visual Studio 调试器
简介
示例(我们正在寻找名为
tbl
的对象):Gomes's method simplified:
Go to Visual Studio (2010) Project Properties* → Debug tab → Enable unmanaged code debugging.
Set the break point in your code, start debugging (F5).
Open Debug → Windows → Immediate Window.
Enter
.load sos
Enter (replace myObject with the name of your object)
Use the result as the parameter of
!ObjSize
See: SOS.DLL, object Address and Visual Studio debugger
Introduction
Example (we are looking for object named
tbl
):除非它是一个巨大的值类型或实例类型(即数千个字段),否则您唯一需要担心的类型是大型数组或字符串。 当然,要计算出数组的大小,您需要知道元素的大小。
.NET(当前)对齐类型的方式与本机编译器对齐类型的方式大致相同。 基本类型具有自然对齐,通常是最接近其大小的两个整数幂的向上舍入:
当组装类型时,编译器将确保任何给定类型的所有字段的实例内的起始偏移量与边界对齐匹配该类型 - 假设未使用显式布局。
用户定义类型本身具有对齐方式,该对齐方式被计算为其任何字段类型的最高对齐方式。 如果需要的话,可以扩展类型的大小以使类型的大小也对齐。
但当然,所有引用类型在大小和对齐方式上仍然只有 IntPtr.Size,因此引用类型的大小不会影响该类型的数组。
请注意,CLR 可以自行决定选择与上述不同的布局类型,可能是为了增加缓存局部性或减少对齐所需的填充。
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:
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.
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.
据估计(2017 年),您可以调试应用程序,在字典生效之前设置断点,拍摄“内存使用情况快照”(选项卡:诊断工具<下的内存使用情况) /em>),填写你的字典并获取另一个快照。
这并不准确,但它是一个很好的猜测。
As an estimate (in 2017) you can debug into your application, set a breakpoint before your dictionary comes to life, take a "Memory Usage Snapshot" (Tab: Memory Usage under Diagnostic Tools), fill your dictionary and get another snapshot.
It is not exact, but it is a good guesstimate.
在像
Dictionary
这样的情况下,您可以通过二进制序列化来获取对象大小。 这是示例代码:In cases like
Dictionary<TKey, TValue>
, you can hack getting the object size by binary serialization. Here is a sample code: