有人可以解释垃圾收集器的行为吗?
我正在玩C#中的垃圾收集器(或者更确切地说是CLR?)试图更好地理解C#中的内存管理。
我做了一个小样本程序,它将三个较大的文件读入byte[]
缓冲区。 我想看看,如果
免责声明:我使用Windows任务管理器测量内存消耗并将其四舍五入。 我尝试了好几次,但总的来说还是差不多。
这是我的简单示例程序:
static void Main(string[] args) { Loop(); } private static void Loop() { var list = new List { @"C:UsersPublicMusicSample MusicAmanda.wma", // Size: 4.75 MB @"C:UsersPublicMusicSample MusicDespertar.wma", // Size: 5.92 MB @"C:UsersPublicMusicSample MusicDistance.wma", // Size: 6.31 MB }; Console.WriteLine("before loop"); Console.ReadLine(); foreach (string pathname in list) { // ... code here ... Console.WriteLine("in loop"); Console.ReadLine(); } Console.WriteLine(GC.CollectionCount(1)); Console.WriteLine("end loop"); Console.ReadLine(); }
对于每个测试,我只更改了foreach
循环的内容。 然后我运行程序,在每个Console.ReadLine()
我停止并检查Windows任务管理器中进程的内存使用情况。 我记录了已用过的内存,然后继续返回程序(我知道断点;))。 在循环结束后,我将GC.CollectionCount(1)
写入控制台,以便查看GC跳转的频率(如果有的话)。
结果
测试1:
foreach ( ... ) { byte[] buffer = File.ReadAllBytes(pathname); Console.WriteLine ... }
结果(使用的内存):
before loop: 9.000 K 1. iteration: 13.000 K 2. iteration: 19.000 K 3. iteration: 25.000 K after loop: 25.000 K GC.CollectionCount(1): 2
测试2:
foreach ( ... ) { byte[] buffer = File.ReadAllBytes(pathname); buffer = null; Console.WriteLine ... }
结果(使用的内存):
before loop: 9.000 K 1. iteration: 13.000 K 2. iteration: 14.000 K 3. iteration: 15.000 K after loop: 15.000 K GC.CollectionCount(1): 2
测试3:
foreach ( ... ) { byte[] buffer = File.ReadAllBytes(pathname); buffer = null; GC.Collect(); Console.WriteLine ... }
结果(使用的内存):
before loop: 9.000 K 1. iteration: 8.500 K 2. iteration: 8.600 K 3. iteration: 8.600 K after loop: 8.600 K GC.CollectionCount(1): 3
我不明白的是:
如果有经验丰富的人可以对上面的一些观点有所了解,那对我来说真的很有帮助。 相当有趣的主题imho。
看看你正在将整个WMA文件读入一个数组,我会说这些数组对象是在大对象堆中分配的。 这是一个单独的堆,它以更多malloc类型的方式进行管理(因为压缩垃圾收集在处理大型对象时效率不高)。
大对象堆中的空间是根据不同的规则收集的,并且它不计入主要生成计数,并且即使存储器,您也不会看到测试1和2之间的集合数量的差异正在被重用(所有正在收集的是Array对象,而不是底层字节)。 在测试3中,每次循环时都会强制收集一个集合 – 大对象堆被包含在其中,因此进程的内存使用量不会增加。
TaskManager不是最好的工具。 使用CLR Profiler或简单的事情,使用WriteLine显示GC.GetTotalMemory()
。
GC的主要目的是分配和取消分配大量小对象。 如果你想学习它,写一些创造了很多(小)字符串的东西。 确保您知道“代际GC”的含义。
您当前的实验正在执行大对象堆(LOH),其中包含一整套其他规则和关注点。
给你一个我认为可能对你有用的链接。
https://msdn.microsoft.com/en-us/magazine/ee309515.aspx
-Joe Yu
您通过任务管理器查看的内存使用情况是针对该过程的。 请记住,CLR代表您的应用程序管理内存,因此您通常不会直接在进程内存使用中看到GC堆的使用情况。
分配和释放内存并不是免费的,所以很明显CLR会尝试对其进行优化以降低成本。 因此,当从堆中收集对象时,您可能也可能看不到释放到操作系统的内存。
上述就是C#学习教程:有人可以解释垃圾收集器的行为吗?分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1009471.html