use*_*246 16 .net c# garbage-collection memory-management
在以下程序中,虽然执行了垃圾收集,但不会重新获得内存初始大小的大小.1.内存的初始大小是总内存:16,940字节专用字节8134656
在循环内创建对象,以便在循环外部完成gc collect时释放这些对象,因为这些对象没有其范围.
但GC收集后的内存与初始大小不同总内存:29,476字节专用字节8540160处理数:115
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MemoryLeakTest
{
class Program
{
static void DisplayMemory()
{
Console.WriteLine("Total memory: {0:###,###,###,##0} bytes", GC.GetTotalMemory(true));
Console.WriteLine("Private bytes {0}", System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64);
Console.WriteLine("Handle count: {0}", System.Diagnostics.Process.GetCurrentProcess().HandleCount);
Console.WriteLine();
}
static void Main()
{
DisplayMemory();
GC.Collect();
for (int i = 0; i < 5; i++)
{
Console.WriteLine("--- New object #{0} ---", i + 1);
object o = new object();
GC.Collect();
DisplayMemory();
}
Console.WriteLine("--- press any key to quit ---");
Console.WriteLine();
Console.Read();
GC.Collect();
DisplayMemory();
}
}
}
Output:
=======
Total memory: 16,940 bytes
Private bytes 8134656
Handle count: 115
--- New object #1 ---
Total memory: 25,588 bytes
Private bytes 8540160
Handle count: 115
--- New object #2 ---
Total memory: 25,576 bytes
Private bytes 8540160
Handle count: 115
--- New object #3 ---
Total memory: 25,576 bytes
Private bytes 8540160
Handle count: 115
--- New object #4 ---
Total memory: 25,576 bytes
Private bytes 8540160
Handle count: 115
--- New object #5 ---
Total memory: 25,576 bytes
Private bytes 8540160
Handle count: 115
--- press any key to quit ---
Total memory: 29,476 bytes
Private bytes 8540160
Handle count: 115
*********************************
Run Code Online (Sandbox Code Playgroud)
私有字节和托管堆大小从初始大小增加的原因是什么?
hun*_*aro 24
计算和报告内存使用情况的尝试是以比正在测量的GC对象分配大小多10,000倍的内存的方式处理的.
此外,打印句柄计数不适用于手头的问题(因为在测试中没有打开/关闭句柄)但是它确实导致了大量的内存分配(仅删除该计数将总分配减半).
原始程序试图测量60-120字节对象的分配(取决于它是32位还是64位程序),但它使用的函数每次调用时都会分配600 KB的内存,一半其中大对象堆(LOH).
提供了另一种测试方法,它表明在GC.Collect调用之后所有对象确实消失了.还提供了有关DisplayMemory函数的内存使用情况的详细信息.
创建100k对象然后收集时,托管内存大小不会增加.当只创建和收集5个对象时,进程的私有字节增加大约12 KB,但SoS显示它不是来自托管堆.当你处理非常小的尺寸和物体数量时,你将无法确切地确定发生了什么; 相反,我建议测试非常大量的物体,以便很容易看出是否有物体泄漏.在这种情况下,没有泄漏,没有错,一切都很好.
我用两个工具来查看这个程序的内存使用情况:
在VS 2013 Pro中的性能和诊断工具下运行原始程序,并将"分析方法"设置为".NET内存分配"的结果如下所示.这提供了一个非常快速的线索,分配的内存比想象的要多.请参见图表上方3.6 MB的总分配.如果删除掉落到2,476字节的DisplayMemory调用.
只要您没有在机器上安装.Net 4.5,就可以在VS2010中使用SoS,或者您可以在VS2012中使用Update3; 只需确保在项目中启用非托管调试,并确保启动32位进程,然后在VS调试器的立即窗口中运行".load sos".我用来审查这个问题的命令是"!eeheap -gc"和"!dumpheap -stat".
class Program
{
static void Main()
{
// A few objects get released by the initial GC.Collect call - the count drops from 108 to 94 objects in one test
GC.Collect();
// Set a breakpoint here, run these two sos commands:
// !eeheap -gc
// !dumpheap -stat
for (int i = 0; i < 100000; i++)
{
object o = new object();
}
// Set a breakpoint here, run these two sos commands before this line, then step over and run them again
// !eeheap -gc
// !dumpheap -stat
GC.Collect();
}
}
Run Code Online (Sandbox Code Playgroud)
在分配和收集100,000个System.Objects之后,我们最终得到的对象少于我们开始使用的4个对象,并且托管堆大小比我们开始时小900字节.
垃圾收集按预期工作.
!eeheap -gc
Number of GC Heaps: 1
generation 0 starts at 0x024f23d0
generation 1 starts at 0x024f100c
generation 2 starts at 0x024f1000
ephemeral segment allocation context: none
segment begin allocated size
024f0000 024f1000 024f23dc 0x13dc(5084)
Large object heap starts at 0x034f1000
segment begin allocated size
034f0000 034f1000 034f5380 0x4380(17280)
Total Size: Size: 0x575c (22364) bytes.
------------------------------
GC Heap Size: Size: 0x575c (22364) bytes.
!dumpheap -stat
Statistics:
MT Count TotalSize Class Name
[...]
6ed026b8 1 112 System.AppDomain
6ed025b0 2 168 System.Threading.ThreadAbortException
6ed05d3c 1 284 System.Collections.Generic.Dictionary`2+Entry[[System.Type, mscorlib],[System.Security.Policy.EvidenceTypeDescriptor, mscorlib]][]
6ed03a6c 2 380 System.Int32[]
6ed0349c 20 560 System.RuntimeType
0047fab8 14 1024 Free
6ed02248 32 1692 System.String
6ecefe88 6 17340 System.Object[]
Total 95 objects
Run Code Online (Sandbox Code Playgroud)
!eeheap -gc
Number of GC Heaps: 1
generation 0 starts at 0x024f23d0
generation 1 starts at 0x024f100c
generation 2 starts at 0x024f1000
ephemeral segment allocation context: none
segment begin allocated size
024f0000 024f1000 02617ff4 0x126ff4(1208308)
Large object heap starts at 0x034f1000
segment begin allocated size
034f0000 034f1000 034f5380 0x4380(17280)
Total Size: Size: 0x12b374 (1225588) bytes.
------------------------------
GC Heap Size: Size: 0x12b374 (1225588) bytes.
!dumpheap -stat
Statistics:
MT Count TotalSize Class Name
[...]
6ed024e4 1 84 System.OutOfMemoryException
6ed02390 1 84 System.Exception
6ed026b8 1 112 System.AppDomain
6ed025b0 2 168 System.Threading.ThreadAbortException
6ed05d3c 1 284 System.Collections.Generic.Dictionary`2+Entry[[System.Type, mscorlib],[System.Security.Policy.EvidenceTypeDescriptor, mscorlib]][]
6ed03a6c 2 380 System.Int32[]
6ed0349c 20 560 System.RuntimeType
0047fab8 14 1024 Free
6ed02248 32 1692 System.String
6ecefe88 6 17340 System.Object[]
6ed025e8 100002 1200024 System.Object
Total 100095 objects
Run Code Online (Sandbox Code Playgroud)
!eeheap -gc
Number of GC Heaps: 1
generation 0 starts at 0x024f2048
generation 1 starts at 0x024f2030
generation 2 starts at 0x024f1000
ephemeral segment allocation context: none
segment begin allocated size
024f0000 024f1000 024f2054 0x1054(4180)
Large object heap starts at 0x034f1000
segment begin allocated size
034f0000 034f1000 034f5380 0x4380(17280)
Total Size: Size: 0x53d4 (21460) bytes.
------------------------------
GC Heap Size: Size: 0x53d4 (21460) bytes.
!dumpheap -stat
Statistics:
MT Count TotalSize Class Name
[...]
6ed024e4 1 84 System.OutOfMemoryException
6ed02390 1 84 System.Exception
6ed026b8 1 112 System.AppDomain
0047fab8 9 118 Free
6ed025b0 2 168 System.Threading.ThreadAbortException
6ed05d3c 1 284 System.Collections.Generic.Dictionary`2+Entry[[System.Type, mscorlib],[System.Security.Policy.EvidenceTypeDescriptor, mscorlib]][]
6ed03a6c 2 380 System.Int32[]
6ed0349c 20 560 System.RuntimeType
6ed02248 32 1692 System.String
6ecefe88 6 17340 System.Object[]
Total 91 objects
Run Code Online (Sandbox Code Playgroud)
与System.Object分配相比,DisplayMemory是一个内存耗尽.它正在创建字符串(它们在堆上),并且它调用以获取内存的函数本身使用吨(大约600 KB)的内存.
!eeheap -gc
Number of GC Heaps: 1
generation 0 starts at 0x02321018
generation 1 starts at 0x0232100c
generation 2 starts at 0x02321000
ephemeral segment allocation context: none
segment begin allocated size
02320000 02321000 02323ff4 0x2ff4(12276)
Large object heap starts at 0x03321000
segment begin allocated size
03320000 03321000 03325380 0x4380(17280)
Total Size: Size: 0x7374 (29556) bytes.
------------------------------
GC Heap Size: Size: 0x7374 (29556) bytes.
!dumpheap -stat
Statistics:
MT Count TotalSize Class Name
[...]
6ed05d3c 3 468 System.Collections.Generic.Dictionary`2+Entry[[System.Type, mscorlib],[System.Security.Policy.EvidenceTypeDescriptor, mscorlib]][]
6ed0349c 20 560 System.RuntimeType
6ed02248 38 2422 System.String
6ecefe88 6 17340 System.Object[]
Total 102 objects
Run Code Online (Sandbox Code Playgroud)
!eeheap -gc
Number of GC Heaps: 1
generation 0 starts at 0x023224fc
generation 1 starts at 0x023224f0
generation 2 starts at 0x02321000
ephemeral segment allocation context: none
segment begin allocated size
02320000 02321000 02371ff4 0x50ff4(331764)
Large object heap starts at 0x03321000
segment begin allocated size
03320000 03321000 033653c0 0x443c0(279488)
Total Size: Size: 0x953b4 (611252) bytes.
------------------------------
GC Heap Size: Size: 0x953b4 (611252) bytes.
!dumpheap -stat
Statistics:
MT Count TotalSize Class Name
[...]
6ed02c08 9 954 System.Char[]
006dfac0 17 1090 Free
6ed03aa4 156 1872 System.Int32
6ecffc20 152 3648 System.Collections.ArrayList
6ed05ed4 9 7776 System.Collections.Hashtable+bucket[]
7066e388 152 16416 System.Diagnostics.ProcessInfo
6ed02248 669 20748 System.String
706723e4 152 29184 System.Diagnostics.NtProcessInfoHelper+SystemProcessInformation
6ecefe88 463 48472 System.Object[]
706743a4 2104 75744 System.Diagnostics.ThreadInfo
70666568 2104 151488 System.Diagnostics.NtProcessInfoHelper+SystemThreadInformation
6ed0d640 2 262168 System.Int64[]
Total 6132 objects
Run Code Online (Sandbox Code Playgroud)
GC.Collect 是异步的,因此在 GC.Collect() 之后直接调用 DisplayMemory() 的逻辑;是值得怀疑的。 同步运行 GC.Collect有一些关于 GC.WaitForPendingFinalizers() 的详细信息。
编辑-回答你的问题:
Total memory: 84,280 bytes
Private bytes 15384576
Handle count: 245
--- New object #1 ---
Total memory: 86,408 bytes
Private bytes 15908864
Handle count: 245
--- New object #2 ---
Total memory: 86,408 bytes
Private bytes 15908864
Handle count: 245
--- New object #3 ---
Total memory: 86,408 bytes
Private bytes 15908864
Handle count: 245
--- New object #4 ---
Total memory: 86,408 bytes
Private bytes 15908864
Handle count: 245
--- New object #5 ---
Total memory: 86,408 bytes
Private bytes 15908864
Handle count: 245
Run Code Online (Sandbox Code Playgroud)
所以这里似乎没有太大区别!
归档时间: |
|
查看次数: |
8654 次 |
最近记录: |