我正在尝试使用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任务管理器中进程的内存使用情况。我记录了已用内存,然后继续使用return运行程序(我知道断点 ;))。就在循环结束后,我向控制台写入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
Test 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仍然表示它已经收集了两次(
GC.CollectionCount
)。为什么? - 在测试2中,显然设置
buffer
为null
有所帮助。内存比测试1低。但为什么GC.CollectionCount
输出2而不是3?为什么内存使用量不如测试3低? - 测试3使用的内存最少。我认为这是因为1.对内存的引用被删除(将
buffer
设置为null
),因此当通过GC.Collect()
调用垃圾回收器时,它可以释放内存。似乎非常清楚。
如果有更多经验的人能够解决上述一些问题,那真的会对我很有帮助。我认为这是一个非常有趣的话题。
.locals
,还是只有 #1 包含? - Pavel Minaev