Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.NET垃圾收集-它会影响什么?_.net_Garbage Collection - Fatal编程技术网

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

.NET垃圾收集-它会影响什么?,.net,garbage-collection,.net,Garbage Collection,在这种情况下,我们考虑在RAM非常低(平均使用3.6/4GB)的服务器上强制执行垃圾收集。不,很遗憾,这不是升级此服务器的真正选项

在这种情况下,我们考虑在RAM非常低(平均使用3.6/4GB)的服务器上强制执行垃圾收集。不,很遗憾,这不是升级此服务器的真正选项

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


问题是:我正在考虑在进程进入睡眠之前添加一个垃圾收集。此框中还有其他正在执行.NET相关任务的服务。当我在这个服务进程中调用垃圾收集时,GC会影响盒子上所有其他与.NET相关的进程,还是只影响请求收集的进程?我有点担心为我关心的进程之外的进程造成某种性能问题。

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

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

物理内存到进程地址空间的映射是一件复杂的事情。NET进程中的垃圾收集可能会增加托管堆中的可用空间,但不能保证会减少工作集大小(Win32进程的内存是从操作系统提供的)。即使你能让这样一个计划起作用——它充其量也很脆弱,在任何情况下都可能行不通


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

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

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重新分配。此外,.NETGC是反应式的,使用程序行为来提高其效率。通过强制收集,您不允许GC根据程序的行为调整自身,从而进一步降低性能


我从经验中知道这一点——我问了一会儿,甚至想出了一个基于计时器的类,在离开高内存操作(每5分钟运行一次)后调用上述方法。在这之后,进程工作集将通过将其交换到磁盘而大大减少自身。在接下来的几秒钟内,它将读回最常用的部分,几分钟后(当任务再次运行时),它将再次执行一系列分配。计时(甚至不分析)该过程表明,在收集过程中,在从操作系统为任务分配VM的过程中,大约有0.2秒(!)的速度减慢。

您最好拿出一个分析程序,看看为什么没有有效地对对象进行垃圾收集。这可能是因为它们不必要地出现在gen2中,您可以对其进行重构,使其能够更快地删除对象

您还可以尝试确保.NET部件与垃圾收集器的服务器版本一起运行,默认版本为工作站版本,这更倾向于保持进程处于活动状态,而不是运行GC(即,它经过调优以保持UI响应)。服务器版本更具攻击性,运行并行GCs,每个核心一个

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

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


链接到

以及其他直接涉及GC.Collect使用的答案,我建议您不仅要做一些简单的分析,还要做一次代码检查,确保在使用完资源后正确地释放它们

使用完所有实现IDisposable的对象后,是否对它们调用Dispose?如果您有包含实现IDisposable的私有变量的类,那么包含的类是否实现IDisposable以及是否调用Dispose


是否存在可以使用using语句确保调用Dispose的位置?这些东西对物理内存都没有帮助,但对诸如windows对象句柄之类的东西会有帮助。

这方面的参考资料会很方便。我能够找到的文档表明,GC可以影响所有应用程序域,或者只影响一个应用程序域。我假设当你强制它时,它只会影响调用者,但是看到它会很高兴。AppDomain!=过程AppDomain是进程内的.NET构造,具有不同的安全设置、堆等。它几乎是一个小进程,可用于加载具有不同安全设置等的插件。好的一点-我忘记了进程中有多个AppDomain。+1,影响多个AppDomain肯定是可能的,但这不是我理解问题的方式。顺便说一句,如果您持有600 MB的.NET托管资源10分钟,强制垃圾收集可能无法释放这些资源。它们可能仍然由.NET进程本身中的某些内容持有。您确定没有任何对挂起的资源的活动引用吗?有一个对使web服务器可用的类的活动引用