.NET垃圾收集 - 它有什么影响?

时间:2010-01-08 15:07:42

标签: .net garbage-collection

我们有一种情况,我们正在考虑在内存非常低的服务器上强制进行垃圾收集(平均使用3.6 / 4GB)。不,不幸的是,升级此服务器并不是一个真正的选择。

我们的一个服务进程(用C ++间接编写(不要问...))可以使用.NET组件,然后睡10分钟。当该服务处于休眠状态时,它通常会挂在可以与其他进程共享的600MB RAM上。似乎某种方式与WSE跟踪有关,用于调试。我可以看到它在第一次COM调用.NET的下一次迭代时唤醒和GC - 然而这个过程做了一些工作,当它进入睡眠状态时,RAM使用量大约回到600MB ......好吧,你可以看出这是怎么回事......

问题:我正在考虑在进程进入睡眠状态之前添加垃圾回收。此框中还有其他服务正在执行与.NET相关的任务。当我在此服务进程中调用垃圾收集时,该GC是否会影响该框中所有其他与.NET相关的进程,还是仅影响请求收集的进程?我有点担心在我关心的过程之外为进程创建某种性能问题。

5 个答案:

答案 0 :(得分:10)

它只会影响调用GC的进程。

答案 1 :(得分:8)

它只影响它调用的进程(但会影响进程中的所有Application Domains)。但是,请注意,这不会释放内存到操作系统。如果要将内存释放到操作系统,可以采用以下方法:

private static void minimizeMemory()
{
    GC.Collect(GC.MaxGeneration);
    GC.WaitForPendingFinalizers();
    SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle,
        (UIntPtr) 0xFFFFFFFF, (UIntPtr) 0xFFFFFFFF);
}

[DllImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SetProcessWorkingSetSize(IntPtr process,
    UIntPtr minimumWorkingSetSize, UIntPtr maximumWorkingSetSize);

这里最大的警告是为什么。除非你注意到内存是颠簸或交换是一个性能瓶颈(或者你正在编写最终用户应用程序),否则没有理由担心内存使用情况。强制GC可能很慢。减少堆将导致需要从VM重新分配堆。此外,.NET GC具有反应性,使用程序行为来提高其效率。通过强制收集,您不允许GC根据程序的行为进行调整,从而进一步降低性能。

我从经验中知道这一点 - 我前一段时间问过this question,甚至提出了一个基于计时器的类,在离开高内存操作(每5分钟运行一次)后调用上面的方法。在此之后,进程工作集会自行减少很多 - 通过将其交换到磁盘。在接下来的几秒钟内,它将回读最常用的部分,几分钟后(当任务再次运行时),它将再次进行一堆分配。时间(甚至不是剖析)该过程表明,对于该任务,在从操作系统分配VM的过程中,约为0.2秒(!)减速。

答案 2 :(得分:5)

明智的做法是找到一个分析器,看看为什么对象没有被有效地垃圾收集。可能是他们不可能在gen2中结束,你可以重构它以允许它更快地摆脱对象。

你也可以尝试确保.NET部分与垃圾收集器的服务器版本一起运行,默认是工作站版本,这更喜欢保持进程活动而不是运行GC(即它被调整为保持UI响应)。服务器版本更具侵略性并且运行并行GC,每个核心也有一个。

将以下内容添加到app.config:

<Configuration>
    <runtime>
        <gcServer enabled=“true“ />
    </runtime>
</Configuration> 

Linky to more information

答案 3 :(得分:4)

除了在收集期间额外的CPU利用率之外,强制垃圾收集不会对其他.NET进程产生影响。但是,在大多数情况下,强制垃圾收集不会导致物理内存的释放。

物理内存到进程地址空间的映射是一件复杂的事情。 .NET进程中的垃圾收集可能会增加托管堆中的可用空间 - 但不能保证会导致工作集大小减少(从操作系统获取Win32进程的内存)。即使你可以让这样的计划有效 - 它最多也会很脆弱,并且可能无法在任何情况下都有效。

有一个名为SetProcessWorkingSetSize()的Win32方法,它允许您控制分配给进程的最小和最大物理内存。您可能希望结合您正在探索的强制收集方案来研究它。

答案 4 :(得分:2)

除了直接引用您使用GC.Collect的其他答案外,我建议您不仅要进行一些简单的分析,还要进行代码审查,并确保在使用完资源后正确地释放资源。

在完成使用IDisposable的所有对象上,您是否调用Dispose?如果您的类包含实现IDisposable的私有变量,那么包含的类是否实现了IDisposable并且您是否调用Dispose?

是否有可以使用using语句来确保调用Dispose的地方?这些东西都不会对物理内存有所帮助,但它会对HANDLE和windows对象之类的东西有所帮助。