C# .NET 应用程序如何实时避免垃圾回收?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/85283/
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-03 11:24:59  来源:igfitidea点击:

How to avoid garbage collection in real time .NET application?

提问by Seb

I'm writting a financial C# application which receive messages from the network, translate them into different object according to the message type and finaly apply the application business logic on them.

我正在编写一个金融 C# 应用程序,它从网络接收消息,根据消息类型将它们转换为不同的对象,最后将应用程序业务逻辑应用于它们。

The point is that after the business logic is applied, I'm very sure I will never need this instance again. Rather than to wait for the garbage collector to free them, I'd like to explicitly "delete" them.

重点是,在应用了业务逻辑之后,我很确定我再也不会需要这个实例了。我不想等待垃圾收集器释放它们,而是想明确地“删除”它们。

Is there a better way to do so in C#, should I use a pool of object to reuse always the same set of instance or is there a better strategy.

在 C# 中是否有更好的方法来做到这一点,我应该使用对象池来重用始终相同的实例集还是有更好的策略。

The goal being to avoid the garbage collection to use any CPU during a time critical process.

目标是避免垃圾收集在时间关键过程中使用任何 CPU。

采纳答案by Joel Coehoorn

Don't delete them right away. Calling the garbage collector for each object is a bad idea. Normally you reallydon't want to mess with the garbage collector at all, and even time critical processes are just race conditions waiting to happen if they're that sensitive.

不要立即删除它们。为每个对象调用垃圾收集器是一个坏主意。通常情况下,你真的不想惹垃圾收集器,即使是时间关键的进程也只是等待发生的竞争条件,如果它们那么敏感。

But if you know you'll have busy vs light load periods for your app, you might try a more general GC.Collect() when you reach a light period to encourage cleanup before the next busy period.

但是,如果您知道您的应用程序会有繁忙与轻负载时段,那么当您到达轻负载时段时,您可以尝试更通用的 GC.Collect() 以鼓励在下一个繁忙时段之前进行清理。

回答by Thomas

Look here: http://msdn.microsoft.com/en-us/library/bb384202.aspx

看这里:http: //msdn.microsoft.com/en-us/library/bb384202.aspx

You can tell the garbage collector that you're doing something critical at the moment, and it will try to be nice to you.

你可以告诉垃圾收集器你正在做一些关键的事情,它会尽量对你好。

回答by Vinko Vrsalovic

You could have a limited amount of instances of each type in a pool, and reuse the already done with instances. The size of the pool would depend on the amount of messages you'll be processing.

您可以在池中拥有有限数量的每种类型的实例,并重用已完成的实例。池的大小取决于您要处理的消息量。

回答by Simon Steele

Forcing a GC.Collect() is generally a bad idea, leave the GC to do what it does best. It sounds like the best solution would be to use a pool of objects that you can grow if necessary - I've used this pattern successfully.

强制 GC.Collect() 通常是一个坏主意,让 GC 做它最擅长的事情。听起来最好的解决方案是使用一个可以在必要时增长的对象池 - 我已经成功地使用了这种模式。

This way you avoid not only the garbage collection but the regular allocation cost as well.

通过这种方式,您不仅可以避免垃圾收集,还可以避免常规分配成本。

Finally, are you sure that the GC is causing you a problem? You should probably measure and prove this before implementing any perf-saving solutions - you may be causing yourself unnecessary work!

最后,您确定 GC 给您带来了问题吗?在实施任何节省性能的解决方案之前,您可能应该测量并证明这一点 - 您可能会给自己造成不必要的工作!

回答by Simon Steele

In theory the GC shouldn't run if your CPU is under heavy load or unless it really needs to. But if you have to, you may want to just keep all of your objects in memory, perhaps a singleton instance, and never clean them up unless you're ready. That's probably the only way to guarantee when the GC runs.

从理论上讲,如果您的 CPU 负载很重,或者除非确实需要,否则 GC 不应该运行。但是如果必须的话,您可能只想将所有对象保存在内存中,也许是一个单例实例,除非您准备好,否则永远不要清理它们。这可能是保证 GC 何时运行的唯一方法。

回答by Brian Lyttle

If it is absolutely time critical then you should use a deterministic platform like C/C++. Even calling GC.Collect() will generate CPU cycles.

如果绝对时间紧迫,那么您应该使用像 C/C++ 这样的确定性平台。即使调用 GC.Collect() 也会产生 CPU 周期。

Your question starts off with the suggestion that you want to save memory but getting rid of objects. This is a space critical optimization. You need to decide what you really want because the GC is better at optimizing this situation than a human.

您的问题始于您想要节省内存但摆脱对象的建议。这是空间关键优化。您需要决定自己真正想要什么,因为 GC 比人类更擅长优化这种情况。

回答by icelava

Get a good understanding and feel on how the Garbage Collector behaves, and you will understand why what you are thinking of here is not recommended. unless you really like the CLR to spend time rearranging objects in memory alot.

对垃圾收集器的行为有一个很好的理解和感受,你就会明白为什么不推荐你在这里想什么。除非您真的喜欢 CLR 花费大量时间重新排列内存中的对象。

回答by Wayne Bloss

Instead of creating a new instance of an object every time you get a message, why don't you reuse objects that have already been used? This way you won't be fighting against the garbage collector and your heap memory won't be getting fragmented.**

与其在每次收到消息时都创建一个对象的新实例,为什么不重用已经使用过的对象呢?这样你就不会与垃圾收集器作斗争,你的堆内存也不会变得碎片化。**

For each message type, you can create a pool to hold the instances that are not in use. Whenever you receive a network message, you look at the message type, pull a waiting instance out of the appropriate pool and apply your business logic. After that, you put that instance of the message object back into it's pool.

对于每种消息类型,您可以创建一个池来保存未使用的实例。每当您收到网络消息时,您都会查看消息类型,从适当的池中提取一个等待实例并应用您的业务逻辑。之后,您将该消息对象的实例放回其池中。

You will most likely want to "lazy load" your pool with instances so your code scales easily. Therefore, your pool class will need to detect when a null instance has been pulled and fill it up before handing it out. Then when the calling code puts it back in the pool it's a real instance.

您很可能希望使用实例“延迟加载”您的池,以便您的代码轻松扩展。因此,您的池类将需要检测何时拉出空实例并在分发之前将其填满。然后当调用代码将它放回池中时,它就是一个真实的实例。

** "Object pooling is a pattern to use that allows objects to be reused rather than allocated and deallocated, which helps to prevent heap fragmentation as well as costly GC compactions."

**“对象池是一种使用模式,它允许对象被重用而不是分配和解除分配,这有助于防止堆碎片以及代价高昂的 GC 压缩。”

http://geekswithblogs.net/robp/archive/2008/08/07/speedy-c-part-2-optimizing-memory-allocations---pooling-and.aspx

http://geekswithblogs.net/robp/archive/2008/08/07/speedy-c-part-2-optimizing-memory-allocations---pooling-and.aspx

回答by NM.

Attempting to second-guess the garbage collector is generally a very bad idea. On Windows, the garbage collector is a generational oneand can be relied upon to be pretty efficient. There are some noted exceptions to this general rule - the most common being the occurrence of a one-time event that you know for a fact will have caused a lot of old objects to die - once objects are promoted to Gen2 (the longest lived) they tend to hang around.

试图重新猜测垃圾收集器通常是一个非常糟糕的主意。在 Windows 上,垃圾收集器是分代的,可以信赖它是非常高效的。这个一般规则有一些值得注意的例外 - 最常见的是一次性事件的发生,你知道一个事实会导致许多旧对象死亡 - 一旦对象被提升到 Gen2(寿命最长的)他们倾向于闲逛。

In the case you mention, you sound as though you are generating a number of short-lived objects - these will result in Gen0 collections. These happen relatively often anyway, and are the most efficient. You could avoid them by having a reusable pool of objects, if you prefer, but it is best to ascertain for certain if GC is a performance problem before taking such action - the CLR profiler is the tool for doing this.

在您提到的情况下,听起来好像您正在生成许多短期对象 - 这些将导致 Gen0 集合。无论如何,这些相对经常发生,并且是最有效的。如果您愿意,您可以通过使用可重用的对象池来避免它们,但最好在采取此类操作之前确定 GC 是否是性能问题 - CLR 分析器是执行此操作的工具。

It should be noted that the garbage collector is different on different .NET frameworks - on the compact framework (which runs on the Xbox 360 and on mobile platforms) it is a non-generational GC and as such you must be much more careful about what garbage your program generates.

应该注意的是,垃圾收集器在不同的 .NET 框架上是不同的——在紧凑型框架(在 Xbox 360 和移动平台上运行)上,它是一个非分代 GC,因此你必须更加小心你的程序产生的垃圾。

回答by Phil Bennett

You hit in yourself -- use a pool of objects and reuse those objects. The semantics of the calls to those object would need to be hidden behind a factory facade. You'll need to grow the pool in some pre-defined way. Perhaps double the size everytime it hits the limit -- a high water algorithm, or a fixed percentage. I'd really strongly advise you not to call GC.Collect().

您自己动手 - 使用对象池并重用这些对象。对这些对象的调用的语义需要隐藏在工厂外观后面。您需要以某种预定义的方式扩大池。每次达到限制时,大小可能会增加一倍——高水算法,或固定百分比。我真的强烈建议你不要调用 GC.Collect()。

When the load on your pool gets low enough you could shrink the pool and that will eventually trigger a garbage collection -- let the CLR worry about it.

当您的池上的负载变得足够低时,您可以缩小池,这最终会触发垃圾收集——让 CLR 担心。