我正在玩C#中的垃圾收集器(或者更确切地说是CLR?)试图更好地理解C#中的内存管理.
我制作了一个小样本程序,它将三个较大的文件读入byte []缓冲区.我想看看,如果
>我实际上需要做任何事情来处理内存效率
>在当前迭代结束后将byte []设置为null时会产生任何影响
>最后,如果通过GC.Collect()强制进行垃圾收集会有所帮助
免责声明:我使用Windows任务管理器测量内存消耗并将其四舍五入.我尝试了好几次,但总的来说还是差不多.
这是我的简单示例程序:
static void Main(string[] args) { Loop(); } private static void Loop() { var list = new List<string> { @"C:\Users\Public\Music\Sample Music\Amanda.wma",// Size: 4.75 MB @"C:\Users\Public\Music\Sample Music\Despertar.wma",// Size: 5.92 MB @"C:\Users\Public\Music\Sample Music\Distance.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
我不明白的是:
>在测试1中,内存随着每次迭代而增加.因此我想在循环结束时不释放内存.但是GC仍然说它收集了2次(GC.CollectionCount).怎么会这样?
>在测试2中,显然有助于将缓冲区设置为null.内存低于测试2.但为什么GC.CollectionCount输出2而不是3?为什么内存使用率不如测试3中的低?
>测试3使用最少的内存.我会说是这样的,因为1.删除了对内存的引用(缓冲区设置为null),因此当通过GC.Collect()调用垃圾收集器时,它可以释放内存.看起来很清楚.
如果有经验丰富的人可以对上述一些观点有所了解,那对我来说真的很有帮助.相当有趣的主题imho.