C# 什么时候可以调用 GC.Collect?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/478167/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 04:57:21  来源:igfitidea点击:

When is it acceptable to call GC.Collect?

c#.netgarbage-collection

提问by Brian Rasmussen

The general advise is that you should not call GC.Collectfrom your code, but what are the exceptions to this rule?

一般的建议是你不应该GC.Collect从你的代码中调用,但是这个规则有什么例外?

I can only think of a few very specific cases where it may make sense to force a garbage collection.

我只能想到一些非常具体的情况,在这些情况下强制垃圾收集可能是有意义的。

One example that springs to mind is a service, that wakes up at intervals, performs some task, and then sleeps for a long time. In this case, it may be a good idea to force a collect to prevent the soon-to-be-idle process from holding on to more memory than needed.

我想到的一个例子是服务,它每隔一段时间醒来,执行一些任务,然后长时间休眠。在这种情况下,强制收集以防止即将空闲的进程持有比需要更多的内存可能是一个好主意。

Are there any other cases where it is acceptable to call GC.Collect?

还有其他情况可以打电话GC.Collect吗?

采纳答案by Jon Skeet

If you have good reason to believe that a significant set of objects - particularly those you suspect to be in generations 1 and 2 - are now eligible for garbage collection, and that now would be an appropriate time to collect in terms of the small performance hit.

如果您有充分的理由相信一组重要的对象(尤其是您怀疑属于第 1 代和第 2 代的对象)现在有资格进行垃圾回收,那么就性能影响较小而言,现在是进行回收的合适时机.

A good example of this is if you've just closed a large form. You know that all the UI controls can now be garbage collected, and a very short pause as the form is closed probably won't be noticeable to the user.

一个很好的例子是,如果您刚刚关闭了一个大表单。您知道所有 UI 控件现在都可以进行垃圾回收,并且用户可能不会注意到表单关闭时的非常短的暂停。

UPDATE 2.7.2018

2018 年 7 月 2 日更新

As of .NET 4.5 - there is GCLatencyMode.LowLatencyand GCLatencyMode.SustainedLowLatency. When entering and leaving either of these modes, it is recommended that you force a full GC with GC.Collect(2, GCCollectionMode.Forced).

从 .NET 4.5 开始 - 有GCLatencyMode.LowLatencyGCLatencyMode.SustainedLowLatency. 在进入和离开这些模式中的任何一种时,建议您使用 强制执行完整 GC GC.Collect(2, GCCollectionMode.Forced)

As of .NET 4.6 - there is the GC.TryStartNoGCRegionmethod (used to set the read-only value GCLatencyMode.NoGCRegion). This can itself, perform a full blocking garbage collection in an attempt to free enough memory, but given we are disallowing GC for a period, I would argue it is also a good idea to perform full GC before and after.

从 .NET 4.6 开始 - 有GC.TryStartNoGCRegion方法(用于设置只读值GCLatencyMode.NoGCRegion)。这本身可以执行完整的阻塞垃圾收集以尝试释放足够的内存,但鉴于我们在一段时间内禁止 GC,我认为在之前和之后执行完整 GC 也是一个好主意。

Source: Microsoft engineer Ben Watson's: Writing High-Performance .NET Code, 2nd Ed. 2018.

资料来源:Microsoft 工程师 Ben Watson 的:编写高性能 .NET 代码,第 2 版。2018 年。

See:

看:

回答by M4N

Have a look at this article by Rico Mariani. He gives two rules when to call GC.Collect (rule 1 is: "Don't"):

看看 Rico Mariani 的这篇文章。他给出了何时调用 GC.Collect 的两条规则(规则 1 是:“不要”):

When to call GC.Collect()

何时调用 GC.Collect()

回答by Brian

One case is when you are trying to unit test code that uses WeakReference.

一种情况是当您尝试对使用WeakReference 的代码进行单元测试时。

回答by casperOne

In your example, I think that calling GC.Collect isn't the issue, but rather there is a design issue.

在您的示例中,我认为调用 GC.Collect 不是问题,而是设计问题。

If you are going to wake up at intervals, (set times) then your program should be crafted for a single execution (perform the task once) and then terminate. Then, you set the program up as a scheduled task to run at the scheduled intervals.

如果您打算每隔一段时间醒来(设定时间),那么您的程序应该为单次执行(执行一​​次任务)而设计,然后终止。然后,将程序设置为计划任务以按计划的时间间隔运行。

This way, you don't have to concern yourself with calling GC.Collect, (which you should rarelyif ever, have to do).

这样,您就不必担心调用 GC.Collect(您应该很少这样做,如果有的话)。

That being said, Rico Mariani has a great blog post on this subject, which can be found here:

话虽如此,Rico Mariani 在这个主题上有一篇很棒的博客文章,可以在这里找到:

http://blogs.msdn.com/ricom/archive/2004/11/29/271829.aspx

http://blogs.msdn.com/ricom/archive/2004/11/29/271829.aspx

回答by ctacke

Scott Holden's blog entry on when to (and when not to) call GC.Collectis specific to the .NET Compact Framework, but the rules generally apply to all managed development.

Scott Holden关于何时(以及何时不)调用 GC.Collect博客条目是特定于.NET Compact Framework 的,但这些规则通常适用于所有托管开发。

回答by BankZ

The short answer is: never!

简短的回答是:从不!

回答by Marc Gravell

I use GC.Collectonly when writing crude performance/profiler test rigs; i.e. I have two (or more) blocks of code to test - something like:

GC.Collect只在编写粗略的性能/分析器测试台时使用;即我有两个(或更多)代码块要测试 - 例如:

GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
TestA(); // may allocate lots of transient objects
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
TestB(); // may allocate lots of transient objects
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
...

So that TestA()and TestB()run with as similar state as possible - i.e. TestB()doesn't get hammered just because TestAleft it very close to the tipping point.

因此,TestA()TestB()以尽可能相似的状态运行 - 即TestB()不会因为TestA非常接近临界点而受到打击。

A classic example would be a simple console exe (a Mainmethod sort-enough to be posted here for example), that shows the difference between looped string concatenation and StringBuilder.

一个经典的例子是一个简单的控制台 exe(例如Main一种足以在此处发布的排序方法),它显示了循环字符串连接和StringBuilder.

If I need something precise, then this would be two completely independent tests - but often this is enough if we just want to minimize (or normalize) the GC during the tests to get a rough feel for the behaviour.

如果我需要一些精确的东西,那么这将是两个完全独立的测试 - 但如果我们只想在测试期间最小化(或标准化)GC 以获得对行为的粗略感觉,这通常就足够了。

During production code? I have yet to use it ;-p

在生产代码期间?我还没有使用它;-p

回答by Chris S

This isn't that relevant to the question, but for XSLT transforms in .NET (XSLCompiledTranform) then you might have no choice. Another candidate is the MSHTML control.

这与问题无关,但对于 .NET (XSLCompiledTranform) 中的 XSLT 转换,您可能别无选择。另一个候选是 MSHTML 控件。

回答by Joel Coehoorn

You can call GC.Collect() when you know something about the nature of the app the garbage collector doesn't. It's tempting to think that, as the author, this is very likely. However, the truth is the GC amounts to a pretty well-written and tested expert system, and it's rare you'll know something about the low level code paths it doesn't.

当您了解垃圾收集器不了解的应用程序性质时,您可以调用 GC.Collect()。很容易认为,作为作者,这很有可能。然而,事实是 GC 相当于一个编写良好且经过测试的专家系统,您很少会了解它不了解的低级代码路径。

The best example I can think of where you might have some extra information is a app that cycles between idle periods and very busy periods. You want the best performance possible for the busy periods and therefore want to use the idle time to do some clean up.

我能想到的最好的例子是你可能有一些额外信息的应用程序,它在空闲时段和非常繁忙的时段之间循环。您希望在繁忙时段获得最佳性能,因此希望使用空闲时间进行一些清理。

However, most of the time the GC is smart enough to do this anyway.

然而,在大多数情况下,GC 足够聪明,无论如何都可以做到这一点。

回答by Ian Ringrose

The best practise is to not force a garbage collection in most cases.(Every system I have worked on that had forced garbage collections, had underlining problems that if solved would have removed the need to forced the garbage collection, and speeded the system up greatly.)

最佳做法是在大多数情况下不强制进行垃圾回收。(我工作过的每个系统都有强制垃圾收集,有强调的问题,如果解决这些问题将消除强制垃圾收集的需要,并大大加快系统速度。)

There are a few caseswhen youknow more about memory usage then the garbage collector does. This is unlikely to be true in a multi user application, or a service that is responding to more then one request at a time.

在某些情况下比垃圾收集器更了解内存使用情况。这在多用户应用程序或一次响应多个请求的服务中不太可能是真的。

However in some batch type processingyou do know more then the GC. E.g. consider an application that.

但是,在某些批处理类型中,您确实比 GC 了解得更多。例如,考虑一个应用程序。

  • Is given a list of file names on the command line
  • Processes a single file then write the result out to a results file.
  • While processing the file, creates a lot of interlinked objects that can not be collected until the processing of the file have complete (e.g. a parse tree)
  • Does not keep match state between the files it has processed.
  • 在命令行上给出文件名列表
  • 处理单个文件,然后将结果写入结果文件。
  • 在处理文件时,创建了许多在文件处理完成之前无法收集的相互关联的对象(例如解析树)
  • 不保持它已处理的文件之间的匹配状态

You maybe able to make a case (after careful) testing that you should force a full garbage collection after you have process each file.

可能能够(经过仔细)测试您应该在处理每个文件后强制进行完整的垃圾回收。

Another cases is a service that wakes up every few minutes to process some items, and does not keep any state while it's asleep. Then forcing a full collection just before going to sleep maybe worthwhile.

另一种情况是服务每隔几分钟醒来处理一些项目,并且在它休眠时不保持任何状态。然后在睡觉前强制收集完整的信息可能是值得的。

The only time I would consider forcing a collection is when I know that a lot of object had been created recently and very few objects are currently referenced.

我会考虑强制收集的唯一时间是当我知道最近创建了很多对象并且当前引用的对象很少时。

I would rather have a garbage collection API when I could give it hints about this type of thing without having to force a GC my self.

我宁愿有一个垃圾收集 API,当我可以给它提示这种类型的东西而不必强迫我自己进行 GC 时。

See also "Rico Mariani's Performance Tidbits"

另见“ Rico Mariani 的表演花絮