![]() |
1
109
最好的做法是不要强制垃圾收集。 根据msdn:
但是,如果您能够可靠地测试代码以确认调用collect()不会产生负面影响,那么继续…… 当你不再需要物品时,试着确保它们被清理干净。如果您有自定义对象,请使用“using语句”和IDisposable接口。 在释放内存/垃圾收集等方面,此链接提供了一些很好的实用建议: |
![]() |
2
30
在大多数情况下,最好的做法是不要强制垃圾收集。 (我工作过的每个系统都强制进行垃圾收集,突出了如果解决了这些问题,就不需要强制进行垃圾收集,并且大大加快了系统的速度。) 有一个 少数病例 什么时候? 你 比垃圾收集器更了解内存使用情况。在多用户应用程序或一次响应多个请求的服务中,这不太可能是真的。 然而在一些 批处理类型处理 你知道的比GC还多。例如,考虑一个应用程序。
你 可以 在仔细测试之后,您可以提出这样一种情况:在处理每个文件之后,您应该强制执行完整的垃圾收集。 另一种情况是每隔几分钟唤醒一次以处理某些项目的服务,以及 睡眠时不保持任何状态 . 然后在睡觉前强制进行一次完整的收集 可以 值得。
我宁愿有一个垃圾收集API,当我可以给它关于这类事情的提示,而不必强迫gc我自己的时候。 |
![]() |
3
28
这样看——当垃圾桶达到10%时,把厨房垃圾扔掉是更有效还是先把它装满再把它拿出来? 不让它填满,你就是在浪费时间在外面的垃圾桶里来回走动。这类似于GC线程运行时发生的情况——所有托管线程在运行时都被挂起。如果我没有弄错,GC线程可以在多个AppDomain之间共享,因此垃圾收集会影响所有AppDomain。 当然,你可能会遇到这样一种情况:你不会很快在垃圾桶里添加任何东西——比如说,如果你打算去度假的话。那么,出去之前把垃圾扔掉是个好主意。 这可能是强制GC的一次帮助——如果您的程序空闲,则使用中的内存不会被垃圾收集,因为没有分配。 |
![]() |
4
20
我认为下面给出的例子 Rico Mariani 很好:如果应用程序状态发生重大变化,则触发GC可能是合适的。例如,在文档编辑器中,关闭文档时可以触发GC。 |
![]() |
5
15
在编程中几乎没有绝对的通用指南。有一半的时候,当有人说“你做错了”时,他们只是在宣扬某种教条。在C语言中,它常常害怕诸如自我修改代码或线程之类的事情,在GC语言中,它强制GC,或者阻止GC运行。 正如大多数准则和良好的经验法则(以及良好的设计实践)一样,很少有情况下按照既定的规范工作是有意义的。你必须非常确定你了解这个案例,你的案例真的需要废除惯例,并且你了解你可能造成的风险和副作用。但也有这样的情况。 编程问题的种类繁多,需要灵活的方法。我见过这样的情况:用垃圾收集语言阻塞GC是有意义的,在某些地方触发GC是有意义的,而不是等待它自然发生。95%的时候,这两个都是没有正确处理问题的标志。但每20次就有1次,这可能是一个有效的理由。 |
![]() |
6
13
我学会了不要试图胜过垃圾收集。说了这句话,我就坚持用
|
![]() |
7
9
我最近遇到的一个案例需要手动呼叫
从未调用垃圾收集器,因为使用的托管内存量可以忽略不计,但使用的非托管内存量很大。手动呼叫
|
![]() |
8
8
不确定这是否是一个最佳实践,但在循环中处理大量图像(即创建和处理大量图形/图像/位图对象)时,我定期让gc.collect。 我想我在某个地方读到了gc只在程序(大部分)空闲时运行,而不是在一个密集循环的中间运行,所以它看起来像是一个手动gc可以理解的区域。 |
![]() |
9
7
我认为您已经列出了最佳实践,除非确实需要,否则不要使用它。我强烈建议您更详细地查看代码,如果需要,可以先使用分析工具来回答这些问题。
|
![]() |
10
5
假设您的程序没有内存泄漏,对象会累积,并且不能在第0代中进行gc-ed,因为: 1)它们被长期引用,因此进入gen1&gen2; 2)它们是大型对象(>80k),因此进入LOH(大型对象堆)。Loh不像Gen0、Gen1和Gen2那样进行压缩。 检查“.net memory”的性能计数器,可以看出1)问题实际上不是问题。一般来说,每10个gen0 GC将触发1个gen1 GC,每10个gen1 GC将触发1个gen2 GC。理论上,如果GC0上没有压力(如果程序内存使用确实是有线的),则GC1和GC2永远无法进行GC ED。我从来没有发生过。 对于问题2),您可以检查“.net memory”性能计数器以验证LOH是否膨胀。如果这真的是你的问题,也许你可以创建一个大型的对象池,正如这个博客所建议的那样。 http://blogs.msdn.com/yunjin/archive/2004/01/27/63642.aspx . |
![]() |
11
4
大型对象是在LOH(大型对象堆)上分配的,而不是在Gen0上。如果你说他们不会被0代人收集垃圾,你是对的。我相信它们只有在完整的GC周期(第0、1和2代)发生时才被收集。 也就是说,我相信在另一方面,当您处理大型对象时,GC将更积极地调整和收集内存,并且内存压力正在上升。 很难说是不是要收集,在什么情况下。我以前在处理带有大量控件等的对话框窗口/窗体后执行gc.collect()(因为当窗体及其控件在第2代中结束时,由于创建了许多业务对象/加载了大量数据-显然没有大型对象),但实际上从长远来看,这样做并没有注意到任何正面或负面影响。 |
![]() |
12
4
我想补充一下: 调用gc.collect()(+waitForPendingFinalizers())是本文的一部分。 正如其他人正确提到的,gc.collect()是非确定性集合,由gc本身(clr)决定。 即使添加对WaitForPendingFinalizer的调用,它也可能不具有确定性。 从这个msdn中获取代码 link 并以对象循环迭代为1或2运行代码。您将发现非确定性的含义(在对象的析构函数中设置一个断点)。 准确地说,当wait(等待)只有1(或2)个延迟对象时,不会调用析构函数。 如果代码处理的是非托管资源(例如:外部文件句柄),则必须实现析构函数(或终结器)。 下面是一个有趣的例子: 注释 :如果您已经从msdn尝试过上述示例,则以下代码将清除空气。
我建议,首先分析输出可能是什么,然后运行,然后阅读下面的原因: 只有在程序结束时才隐式调用析构函数。} 为了确定地清理对象,必须实现IDisposable并显式调用Dispose()。这就是本质!:) |
![]() |
13
2
还有一件事,显式触发gc collect可能不会提高程序的性能。很有可能使情况变得更糟。 .NET GC的设计和调优都很好,可以自适应,这意味着它可以根据程序内存使用的“习惯”调整gc0/1/2阈值。因此,它将在运行一段时间后适应您的程序。一旦您显式调用gc.collect,阈值将被重置!而且.NET必须花时间重新适应程序的“习惯”。 我的建议总是信任.NET GC。如果出现内存问题,请检查“.net memory”性能计数器并诊断我自己的代码。 |
![]() |
14
1
建议:不确定时不要执行此操作或任何操作。当已知事实时重新评估,然后在性能测试之前/之后进行验证。 |
![]() |
15
0
imho,这类似于 “如果你能证明你的程序将来永远不会有任何错误,那就继续……” 不管怎样,强制GC对于调试/测试都很有用。如果您觉得您需要在任何其他时间执行,那么您可能是错了,或者您的程序构建错误。不管怎样,解决方案都不会强制GC… |
![]() |
codeforester · 测量GC暂停时间的最佳方法是什么? 6 年前 |
![]() |
Venki WAR · 需要解释G1的并行完整GC 6 年前 |
![]() |
Stephan_Berlin · 为什么CMS系列中的初始标记阶段 6 年前 |
![]() |
Bonsaisteak · 为什么年轻一代需要三个区域来收集垃圾? 7 年前 |
![]() |
goks · 如何清除熊猫的数据帧内存? 7 年前 |