GC.Collect() 之后是否立即进行垃圾回收 运行?
Does garbage collection run immediately after GC.Collect()?
提问仅供研究。
我看了很多关于C#的书,这个问题总是浮现在我的脑海中。据我了解,C# 是托管代码,当 CLR 决定何时 运行 垃圾回收时,所有垃圾回收都会发生。开始吧。
假设我有简单的 class Student
:
public class Student
{
public int IdStudent { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
}
class Program
{
static void Main(string[] args)
{
This is row1: Person person = new Person() {IdPerson=1, Name="Bill", SurName="Collins"};
This is row2: System.GC.Collect();
This is row3: string str="Hello World!";
}
}
请批准或拒绝我的假设:
- 垃圾收集不是 运行 立即在 row2,我说得对吗?
GC.Collect()
只是一个 请求 进行垃圾收集,不会 运行 立即在第 2 行。此行 可能在 x milliseconds/seconds 中执行 。
在我看来,方法 System.GC.Collect();
只是告诉垃圾收集器垃圾收集器应该 运行 垃圾收集,但是 真正的垃圾收集可能发生在 x milliseconds/seconds
只有垃圾收集器知道何时进行垃圾收集运行。并且如果第 0 代中有空闲 space,那么垃圾收集将不会发生在 row2: row2: System.GC.Collect();
不可能立即 运行 垃圾回收,因为我们在托管环境中编程,只有 CLR 决定何时 运行 垃圾回收。 垃圾收集可以是 运行 in x milliseconds/seconds 或者垃圾收集 可能不是 运行 因为有足够的 space in第 0 代在调用方法 GC.Collect()
后创建新对象。程序员可以做的只是要求 CLR 通过 GC.Collect()
.
方法进行 运行 垃圾收集
更新:
我读过 this msdn article about GC.Collect Method ()
.。但是,我不清楚何时开始真正清除未引用的对象。 MSDN 说:
GC.Collect Method () forces an immediate garbage collection of all
generations.
但是,在备注中,我读到了这个:
Use this method to try to reclaim all memory that is inaccessible. It
performs a blocking garbage collection of all generations.
- 我对此感到困惑 "Use this method to TRY" 我认为垃圾回收 可能不会发生 因为 CLR 决定有足够的 space 来创建新对象。我说得对吗?
简答
调用 GC.Collect()
将执行完整的垃圾收集并等待它完成,但它不会等待任何挂起的终结器到 运行。
长答案
您的假设部分正确,因为 运行ning 终结器的 GC 在一个或多个后台线程中 运行。 (但请参阅此答案末尾的脚注。)
但是, 可以在调用 GC.Collect()
:
之后调用 GC.WaitForFullGCComplete()
and GC.WaitForPendingFinalizers()
等待完整的 GC 完成
GC.Collect();
GC.WaitForPendingFinalizers();
GC.WaitForFullGCComplete();
但是,请注意 终结器所在的线程 运行 未指定,因此无法保证此方法会终止。
请注意,您通常不应以这种方式使用 GC;我假设您有一个特殊情况需要解决,或者您这样做是为了研究目的。
我见过的唯一有效的情况是当应用程序正在关闭时,并且您想(尝试)确保所有终结器都已 运行 - 因为,例如,它们将刷新日志文件等
如上所述,这仍然不能保证所有终结器都已 运行;这只是你能做的最好的。
针对您的观点 (5) 的回答:
GC.Collect() 的文档指出:
强制立即对所有代进行垃圾回收。
所以这将强制GC。
文档还指出:
使用此方法尝试回收所有不可访问的内存。
这里使用"try"这个词仅仅意味着即使是full GC运行,也不一定会回收所有无法访问的内存。发生的原因有多种,例如,终结器可能会阻塞。
脚注
.Net 4.5 allows you to specify whether GC.Collect()
is blocking or not.
事实上,GC.Collect()
的文档指出 它执行所有代的阻塞垃圾收集,这似乎与我上面的陈述相矛盾。但是,对于是否真的如此,似乎有些困惑。
参见示例 this thread。
答案是这样的:GC.Collect()
默认等待所有代被GC,但它不会等待挂起的终结器,它们总是在一个单独的线程。
因此,如果你不需要等待终结器,你只需要调用 GC.Collect()
而你不需要等待任何其他东西。
有两个 GC,从您的代码来看,我相信您想了解工作站 GC。 运行 在完全收集期间,哪个并发最大限度地减少了暂停?工作站 GC 使用第二个处理器并发 运行 收集,从而在降低吞吐量的同时最大限度地减少延迟。如果服务器 GC 没有正常工作,我们应该只担心 GC 行为。如果您按照工作站 GC 在代码中添加 GC.collect(),那在服务器 GC 上可能没用。
服务器 GC 旨在实现最大吞吐量,并以非常高的性能进行扩展。服务器上的内存碎片比工作站上的问题严重得多,这使得垃圾收集成为一个有吸引力的提议。在单处理器场景下,两个收集器的工作方式相同:工作站模式,没有并发收集
I am confused by this Use this method to TRY and I think that garbage collection may not occur cause CLR decides that there is enough space to create new objects. Am I right?
对于工作站 GC,GC.Collect 将尽快开始收集,您可以安全地假设它会立即收集。
提问仅供研究。
我看了很多关于C#的书,这个问题总是浮现在我的脑海中。据我了解,C# 是托管代码,当 CLR 决定何时 运行 垃圾回收时,所有垃圾回收都会发生。开始吧。
假设我有简单的 class Student
:
public class Student
{
public int IdStudent { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
}
class Program
{
static void Main(string[] args)
{
This is row1: Person person = new Person() {IdPerson=1, Name="Bill", SurName="Collins"};
This is row2: System.GC.Collect();
This is row3: string str="Hello World!";
}
}
请批准或拒绝我的假设:
- 垃圾收集不是 运行 立即在 row2,我说得对吗?
GC.Collect()
只是一个 请求 进行垃圾收集,不会 运行 立即在第 2 行。此行 可能在 x milliseconds/seconds 中执行 。 在我看来,方法System.GC.Collect();
只是告诉垃圾收集器垃圾收集器应该 运行 垃圾收集,但是 真正的垃圾收集可能发生在 x milliseconds/seconds只有垃圾收集器知道何时进行垃圾收集运行。并且如果第 0 代中有空闲 space,那么垃圾收集将不会发生在 row2:
row2: System.GC.Collect();
不可能立即 运行 垃圾回收,因为我们在托管环境中编程,只有 CLR 决定何时 运行 垃圾回收。 垃圾收集可以是 运行 in x milliseconds/seconds 或者垃圾收集 可能不是 运行 因为有足够的 space in第 0 代在调用方法
GC.Collect()
后创建新对象。程序员可以做的只是要求 CLR 通过GC.Collect()
. 方法进行 运行 垃圾收集
更新:
我读过 this msdn article about GC.Collect Method ()
.。但是,我不清楚何时开始真正清除未引用的对象。 MSDN 说:
GC.Collect Method () forces an immediate garbage collection of all generations.
但是,在备注中,我读到了这个:
Use this method to try to reclaim all memory that is inaccessible. It performs a blocking garbage collection of all generations.
- 我对此感到困惑 "Use this method to TRY" 我认为垃圾回收 可能不会发生 因为 CLR 决定有足够的 space 来创建新对象。我说得对吗?
简答
调用 GC.Collect()
将执行完整的垃圾收集并等待它完成,但它不会等待任何挂起的终结器到 运行。
长答案
您的假设部分正确,因为 运行ning 终结器的 GC 在一个或多个后台线程中 运行。 (但请参阅此答案末尾的脚注。)
但是, 可以在调用 GC.Collect()
:
GC.WaitForFullGCComplete()
and GC.WaitForPendingFinalizers()
等待完整的 GC 完成
GC.Collect();
GC.WaitForPendingFinalizers();
GC.WaitForFullGCComplete();
但是,请注意 终结器所在的线程 运行 未指定,因此无法保证此方法会终止。
请注意,您通常不应以这种方式使用 GC;我假设您有一个特殊情况需要解决,或者您这样做是为了研究目的。
我见过的唯一有效的情况是当应用程序正在关闭时,并且您想(尝试)确保所有终结器都已 运行 - 因为,例如,它们将刷新日志文件等
如上所述,这仍然不能保证所有终结器都已 运行;这只是你能做的最好的。
针对您的观点 (5) 的回答:
GC.Collect() 的文档指出:
强制立即对所有代进行垃圾回收。
所以这将强制GC。
文档还指出:
使用此方法尝试回收所有不可访问的内存。
这里使用"try"这个词仅仅意味着即使是full GC运行,也不一定会回收所有无法访问的内存。发生的原因有多种,例如,终结器可能会阻塞。
脚注
.Net 4.5 allows you to specify whether GC.Collect()
is blocking or not.
事实上,GC.Collect()
的文档指出 它执行所有代的阻塞垃圾收集,这似乎与我上面的陈述相矛盾。但是,对于是否真的如此,似乎有些困惑。
参见示例 this thread。
答案是这样的:GC.Collect()
默认等待所有代被GC,但它不会等待挂起的终结器,它们总是在一个单独的线程。
因此,如果你不需要等待终结器,你只需要调用 GC.Collect()
而你不需要等待任何其他东西。
有两个 GC,从您的代码来看,我相信您想了解工作站 GC。 运行 在完全收集期间,哪个并发最大限度地减少了暂停?工作站 GC 使用第二个处理器并发 运行 收集,从而在降低吞吐量的同时最大限度地减少延迟。如果服务器 GC 没有正常工作,我们应该只担心 GC 行为。如果您按照工作站 GC 在代码中添加 GC.collect(),那在服务器 GC 上可能没用。
服务器 GC 旨在实现最大吞吐量,并以非常高的性能进行扩展。服务器上的内存碎片比工作站上的问题严重得多,这使得垃圾收集成为一个有吸引力的提议。在单处理器场景下,两个收集器的工作方式相同:工作站模式,没有并发收集
I am confused by this Use this method to TRY and I think that garbage collection may not occur cause CLR decides that there is enough space to create new objects. Am I right?
对于工作站 GC,GC.Collect 将尽快开始收集,您可以安全地假设它会立即收集。