垃圾收集和线程

发布于 2024-08-18 05:06:06 字数 533 浏览 7 评论 0原文

据我所知,当 GC 执行其操作时,VM 会阻止所有正在运行的线程,或者至少在压缩堆时是如此。 CLR 和 JVM (截至 2010 年 1 月的生产版本)的现代实现中是否存在这种情况?请不要提供 GC 的基本链接,因为我了解基本的工作原理。

我假设全局锁定是这样的情况,因为当压缩发生时,引用在移动期间可能无效,并且似乎最简单的方法是锁定整个堆(即,通过阻止所有线程来间接实现)。我可以想象更强大的机制,但 KISS 常常占上风。

如果我错了,我的问题将通过对用于最小化阻塞的策略的简单解释来回答。如果我的假设正确,请就以下两个问题提供一些见解:

  1. 如果这确实是这种行为,那么像 JBOSS 和 Glassfish 这样的重量级企业引擎如何保持一致的高 TPS 率?我在 JBOSS 上进行了一些谷歌搜索,希望能在 APACHE 上找到一些东西,比如适合 Web 处理的内存分配器。

  2. 面对 NUMA 式架构(可能在不久的将来),这听起来像是一场灾难,除非进程受到线程和内存分配的 CPU 限制。

AFAIK when a GC is doing its thing the VM blocks all running threads -- or at least when it is compacting the heap. Is this the case in modern implementions of the CLR and the JVM (Production versions as of January 2010) ? Please do not provide basic links on GC as I understand the rudimentary workings.

I assume global locking is the case as when compaction occurs references might be invalid during the move period, and it seems simplest just to lock the entire heap (i.e., indirectly by blocking all threads). I can imagine more robust mechanisms, but KISS often prevails.

If I am incorrect my question would be answered by a simple explanation of the strategy used to minimise blocking. If my assumption is correct please provide some insight on the following two questions:

  1. If this is indeed the behaviour, how do heavyweight enterprise engines like JBOSS and Glassfish maintain a consistantly high TPS rate ? I did some googling on JBOSS and I was expecting to find something on a APACHE like memory allocator suited for web processing.

  2. In the face of NUMA-esque architectures (potentially the near future) this sounds like a disaster unless the processes are CPU bound by thread and memory-allocation.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

你与昨日 2024-08-25 05:06:06

答案是,这取决于所使用的垃圾收集算法。在某些情况下,所有线程在 GC 期间停止是正确的。在其他情况下,您的错误在于垃圾收集是在正常线程运行时进行的。要了解 GC 如何实现这一点,您需要详细了解垃圾收集器的理论和术语,并结合对特定收集器的了解。它根本无法用简单的解释来解释。

哦,是的,值得指出的是,许多现代收藏家本身没有压缩阶段。相反,它们的工作方式是将活动对象复制到新的“空间”,并在完成后将旧的“空间”清零。

如果我错了,我的问题将通过对用于最小化阻塞的策略的简单解释来回答。

如果您确实想了解垃圾收集器的工作原理,我建议:

……请注意,找到生产垃圾收集器内部的准确、详细、公开的描述并不容易。 (尽管在Hotspot GC的情况下,您可以查看源代码...)

编辑:回应OP的评论...

“看来正如我所想——无法回避“停止世界”部分。”

这取决于。对于 Java 6 并发收集器,在标记根(包括堆栈)期间有两次暂停,然后并行进行其他对象的标记/复制。对于其他类型的并发收集器,在收集器运行时使用读或写屏障来捕获收集器和应用程序线程否则会相互干扰的情况。我现在没有[琼斯]的副本,但我还记得可以使“停止世界”间隔可以忽略不计......以更昂贵的指针操作和/或不收集所有内容为代价垃圾。

The answer is that this depends on the garbage collection algorithms used. In some cases, you are correct that all threads are stopped during GC. In other cases, you are incorrect in that garbage collection proceeds while normal threads are running. To understand how GC's achieve that, you need a detailed understanding of the theory and terminology of garbage collectors, combined with an understanding of the specific collector. It is simply not amenable to a simple explanation.

Oh yes, and it is worth pointing out that many modern collectors don't have a compaction phase per-se. Rather they work by copying live objects to a new "space" and zeroing the old "space" when they are done.

If I am incorrect my question would be answered by a simple explanation of the strategy used to minimise blocking.

If you really want to understand how garbage collectors work, I recommend:

... and beware that finding accurate, detailed, public descriptions of the internals of production garbage collectors is not easy. (Though in the case of the Hotspot GC's, you can look at the source code ...)

EDIT: in response to the OP's comment ...

"It seems it is as I thought -- there is no getting around the "stop the world" part."

It depends. In the case of the Java 6 Concurrent Collector, there are two pauses during the marking of the roots (including stacks), and then marking / copying of other objects proceeds in parallel. For other kinds of concurrent collector, read or write barriers are used while the collector is running to trap situations where the collector and application threads would otherwise interfere with each other. I don't have my copy of [Jones] here right now, but I also recall that it is possible to make the "stop the world" interval negligible ... at the cost of more expensive pointer operations and/or not collecting all garbage.

花开浅夏 2024-08-25 05:06:06

您是正确的,垃圾收集器必须暂停所有应用程序线程。 Sun JVM 可以通过使用并发收集器来减少此暂停时间,并发收集器可以在不停止应用程序的情况下执行一些工作,但它仍然必须暂停应用程序线程。

请参阅此处 http://java.sun.com/javase/ Technologies/hotspot/gc/gc_tuning_6.html#par_gc 和此处 http://java.sun.com/javase/technologies/hotspot/gc/gc_tuning_6.html#cms 了解有关 sun JVM 如何在最新 JVM 中管理垃圾收集的详细信息。

对于网络应用程序,我认为这不是问题。由于用户请求应在少量时间内完成< 1s 分配给请求服务的任何临时对象不应退出年轻代(只要其大小适当),在年轻代中它们会被非常有效地清理。其他生命周期较长的数据(例如用户会话)将保留更长时间,并可能影响主要 GC 事件所花费的时间。

在高 TPS 应用程序上,常见策略是使用会话关联和负载平衡在相同或单独的硬件上运行应用程序服务器的多个实例。通过这样做,每个 JVM 的单独堆大小保持较小,从而减少了执行主要收集时 GC 的暂停时间。一般来说,数据库而不是应用程序或 JVM 成为瓶颈。

您可能会发现,与 J2EE 中 Web 特定内存分配器的概念最接近的是由框架和应用程序服务器执行的对象/实例池。例如,在 JBOSS 中,您有 EJB 池和数据库连接池。然而,这些对象通常被池化,因为它们的创建成本较高,而不是垃圾收集开销。

You are correct that the garbage collector will have to pause all the application threads. This pause time can be reduduced with the sun JVM by using the concurrent collector which preforms some of the work without stopping the application, but it stll has to pause the application threads.

See here http://java.sun.com/javase/technologies/hotspot/gc/gc_tuning_6.html#par_gc and here http://java.sun.com/javase/technologies/hotspot/gc/gc_tuning_6.html#cms for details on how the sun JVM manages garbage collection in the latest JVMs.

For web applications I don't think this is an issue. As the user requests should complete within a small amount of time < 1s any temporary objects allocated to service the request should not exit the young generation (providing it is sized appropriately) where they are cleaned up very efficiently. Other data with longer lifecycles such as user sessions will hang around longer and can impact the time spent on major GC events.

On high TPS applications a common strategy is to run multiple instances of the application server either on the same or separate hardware using session affinity and load ballancing. By doing this the individual heap size per JVM is kept smaller which reduced the pause times for GC when performing a major collection. In general the database becomes the bottle neck rather than the application or JVM.

The closest you might find to the concept of a web specific memory allocator in in J2EE is object/instance pooling that is performed by frameworks and application severs. For example in JBOSS you have EJB pools and database connection pools. However these objects are usually pooled because of thier high creation cost rather than the garbage collection overhead.

听风念你 2024-08-25 05:06:06

我相信 IBM 已经针对提高多核系统中的 GC 性能进行了一些研究,其中包括减少或消除“一切停止”问题的工作。

例如参见:
服务器的并行、增量和并发 GC(pdf)

或者谷歌搜索“并发垃圾收集 ibm”之类的内容

I believe IBM have performed some research towards improving GC performance in multi-core systems which includes work on reducing or eliminating the 'everything stop' issue.

E.g. see:
A Parallel, Incremental and Concurrent GC for Servers(pdf)

Or google something like "concurrent garbage collection ibm"

萌无敌 2024-08-25 05:06:06

据我所知,当 GC 执行其操作时,VM 会阻止所有正在运行的线程——或者至少在压缩堆时。 CLR 和 JVM 的现代实现(截至 2010 年 1 月的生产版本)是否属于这种情况?

Sun 的 Hotspot JVM 和 Microsoft 的 CLR 都具有并发 GC,它们仅在短阶段停止世界(以获得可访问所有实时数据的全局根的自洽快照),而不是在整个收集周期内停止世界。我不确定他们的压缩实现,但这种情况非常罕见。

如果确实如此,像 JBOSS 和 Glassfish 这样的重量级企业引擎如何保持持续的高 TPS 率?

这些引擎的延迟比让世界停止所需的时间长几个数量级。此外,延迟被引用为例如 95%,这意味着延迟仅在 95% 的时间里低于引用的时间跨度。因此,压缩不太可能影响引用的延迟。

AFAIK when a GC is doing its thing the VM blocks all running threads -- or at least when it is compacting the heap. Is this the case in modern implementions of the CLR and the JVM (Production versions as of January 2010) ?

Both Sun's Hotspot JVM and Microsoft's CLR have concurrent GCs that stop-the-world only for short phases (to get a self-consistent snapshot of the global roots from which all live data are reachable) and not for entire collection cycles. I'm not sure about their implementations of compaction but that is a very rare occurrence.

If this is indeed the behaviour, how do heavyweight enterprise engines like JBOSS and Glassfish maintain a consistantly high TPS rate?

The latency of those engines is orders of magnitude longer than the time taken to stop the world. Also, latencies are quoted as, for example, 95th percentile meaning that the latency will only be below the quoted time span 95% of the time. So compactions are unlikely to affect quoted latencies.

盛夏已如深秋| 2024-08-25 05:06:06

Java 有许多可用的 GC 算法,但并非所有算法都会阻塞所有正在运行的线程。例如,您可以使用与应用程序同时运行的 -XX:+UseConcMarkSweepGC(用于收集终身生成)。

There are a number of GC algorithms available with Java, not all of which block all running threads. For example, you can use -XX:+UseConcMarkSweepGC which runs concurrently with the app (for collection of the tenured generation).

咿呀咿呀哟 2024-08-25 05:06:06

当前最先进的 Java 垃圾收集仍然涉及偶尔的“停止世界”暂停。 Java 6u14 上引入的 G1 GC 会同时完成大部分工作,但是,当内存非常低并且需要压缩堆时,它必须确保没有人会弄乱其下面的堆。这要求不允许进行任何其他操作。要了解有关 G1 GC 的更多信息,请查看 Sun 的演示

Current state of the art garbage collection for Java still involves occasional "stop the world" pauses. The G1 GC introduced on Java 6u14 does most of it's work concurrently, however, when memory is really low, and it needs to compact the heap, then it has to ensure that no-one messes with the heap underneath it. This requires that nothing else is allowed to proceed. To find out more about the G1 GC, look at the presentations from Sun.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文