C# .NET 中的垃圾收集(几代)

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

Garbage collection in .NET (generations)

c#.netgarbage-collection

提问by SNA

I have read a lot of .NET performance articles that describe Gen1,Gen2 garbage collection and objects surviving the generations.

我已经阅读了很多 .NET 性能文章,这些文章描述了 Gen1、Gen2 垃圾收集和历代幸存的对象。

Why does objects survives the collection?

为什么对象在集合中存活?

What is pinning?

什么是钉钉?

回答by Jim Barnett

Pinning is used to keep the garbage collector from relocating objects. It can hurt performance by restricting what the garbage collector can do. In general pinned objects should be pinned for as short as time as possible.

固定用于防止垃圾收集器重新定位对象。它会通过限制垃圾收集器的功能来损害性能。通常,固定对象的固定时间应尽可能短。

回答by Joel Coehoorn

One reason you have multiple generations in a garbage collector is to avoid losing memory to fragmentation.

在垃圾收集器中有多个代的原因之一是避免因碎片而丢失内存。

Every function call can mean the creation and deletioncollection of multiple objects, and so the memory heap for your program tends to fragment very quickly. This leaves holes behind that aren't very usable. The result is that your program needs to be periodically de-fragmented, just like a hard disk. This is part of what happens during a collection.

每个函数调用都可能意味着创建和删除多个对象的集合,因此程序的内存堆往往会很快碎片化。这留下了不太有用的漏洞。结果是您的程序需要定期进行碎片整理,就像硬盘一样。这是收集期间发生的事情的一部分。

When an object survives a collection, it is moved to a longer-lived generation on the theory that if it survived one collection it will probably survive others. Thus the later generations have less turn-over and don't fragment as much. This means your program spends less time overall juggling things around to clean up holes and wastes less memory. This is also an improvement over traditional memory management (malloc/free or new/delete), which left it up to the operating system to manage any memory fragmentation.

当一个对象在一个集合中幸存下来时,它会被移动到寿命更长的一代,根据理论,如果它在一个集合中幸存下来,它可能会在其他集合中幸存下来。因此,后代的营业额较少,也没有那么多碎片化。这意味着您的程序在整体上花费更少的时间来清理漏洞并浪费更少的内存。这也是对传统内存管理(malloc/free 或 new/delete)的改进,后者让操作系统来管理任何内存碎片。

The reason an object survives collection is because there is something somewhere that is still "in scope" and holds a reference to that object. There are a few ways you can cause this to happen and then forget about the reference, so it is possible to "leak" memory in managed code.

对象在集合中幸存的原因是因为某处仍然“在范围内”并持有对该对象的引用。有几种方法可以导致这种情况发生,然后忘记引用,因此有可能在托管代码中“泄漏”内存。

Sometimes people are tempted to call GC.Collect()in an effort to get the garbage collector to clean something up. Perhaps they've discovered they have a leak, or think memory is becoming over-fragmented. You should resist those urges. While garbage collection in .Net is not perfect, is it verygood, and it's almost certainly much better at cleaning up memory than you are. Odds are that if an object can and should be collected, it will be. Remember that calling GC.Collect()can actually make things worse by helping the garbage collector move objects up to a higher generation, and thus keeping them around for longer than they otherwise would be.

有时人们很想打电话GC.Collect()让垃圾收集器清理一些东西。也许他们已经发现他们有泄漏,或者认为内存变得过度碎片化。你应该抵制这些冲动。虽然 .Net 中的垃圾收集并不完美,但它非常好,而且几乎可以肯定它在清理内存方面比您要好得多。有可能的是,如果一个对象可以而且应该被收集,它就会被收集。请记住,GC.Collect()通过帮助垃圾收集器将对象向上移动到更高代,调用实际上会使事情变得更糟,从而使它们保留的时间比其他方式更长。

Instead, if you suspect you have a leak, look to your own code for something like a global or static variable that might hold a reference to a lot of other items. The only time you should call GC.Collect()is when you have information about the nature of the program that is not available to the garbage collector, and that's pretty rare as the GC knows every reference you've created.

相反,如果您怀疑自己有泄漏,请查看您自己的代码,以查找可能包含对许多其他项目的引用的全局或静态变量之类的东西。您应该调用的唯一时间GC.Collect()是当您获得垃圾收集器无法获得的有关程序性质的信息时,这种情况非常罕见,因为 GC 知道您创建的每个引用。

"Pinning" is for when you need to pass an object to an unmanaged library. The garbage collector can move an object's physical location in memory, and so you need to "pin" it in one place or the pointer used by the unmanaged library could become invalid. A pinned object cannot be collected, and so you shouldn't pin an object for any longer than necessary.

“固定”适用于需要将对象传递给非托管库的情况。垃圾收集器可以移动对象在内存中的物理位置,因此您需要将它“固定”在一个位置,否则非托管库使用的指针可能会变得无效。无法收集固定对象,因此您不应将对象固定超过必要时间。

回答by mfawzymkh

http://blogs.msdn.com/maoni/is a good resource.
Asking questions here helps too :)

http://blogs.msdn.com/maoni/是一个很好的资源。
在这里提问也有帮助:)

For your questions:

对于您的问题:

Why do objects survive the collection:
Objects survive a collection when they are "live objects", or "Reachable objects". Reachable objects are objects where there is a reference to them from another object that is on:

为什么对象会在集合中
存活:当对象是“活动对象”或“可访问对象”时,它们会在集合中存活。可到达的对象是从另一个对象引用到它们的对象:

  1. The stack
  2. The finalization queue
  3. another object in a higher generation ( for example a Gen2 Object holding a reference to a Gen0 Object )
  4. The handle table ( a data structure used by the CLR, and require a seperate post on its own:) )
  1. 堆栈
  2. 最终确定队列
  3. 更高代中的另一个对象(例如,持有对 Gen0 对象的引用的 Gen2 对象)
  4. 句柄表(CLR 使用的数据结构,需要单独发帖:))

What is Pinning:
Pinning means making sure the object doesn't move in memory. objects move in memory as a result of a compacting GC, you can create a GCHandle of typed pinned if you want to pin an object, pinning also happens automatically behind the sciene for objects that are passed to native code via PInvoke ( like strings that are passed as output, the internal buffer gets pinned during the call to PInvoke ).

什么是固定:
固定意味着确保对象不会在内存中移动。作为压缩 GC 的结果,对象在内存中移动,如果您想固定一个对象,您可以创建一个固定类型的 GCHandle,对于通过 PInvoke 传递给本机代码的对象(例如作为输出传递,内部缓冲区在调用 PInvoke 期间被固定)。

Check out http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.gchandle.aspxfor a good example about GCHandle.

查看http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.gchandle.aspx以获得关于 GCHandle 的一个很好的例子。