代码之家  ›  专栏  ›  技术社区  ›  Hassan Syed

垃圾收集和线程

  •  21
  • Hassan Syed  · 技术社区  · 15 年前

    当GC执行它的操作时,VM会阻塞所有正在运行的线程——或者至少当它压缩堆时。在现代的clr和jvm实现中是这样吗? (截至2010年1月的生产版本) ?请不要提供GC上的基本链接,因为我了解基本工作原理。

    我假设全局锁定是这样的,因为当压缩发生时,在移动期间引用可能无效,并且锁定整个堆似乎最简单(即通过阻塞所有线程间接锁定)。我能想象出更强大的机制,但接吻经常盛行。

    如果我是错误的,我的问题会得到一个简单的解释,以减少阻塞的策略。如果我的假设是正确的,请提供以下两个问题的一些见解:

    1. 如果这确实是一种行为,那么像jboss和glassfish这样的重量级企业引擎如何保持始终如一的高TPS率呢?我在jboss上做了一些谷歌搜索,我希望在类似Apache的内存分配器上找到适合Web处理的东西。

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

    6 回复  |  直到 9 年前
        1
  •  16
  •   dpercy skamradt    9 年前

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

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

    如果我是错误的,我的问题会得到一个简单的解释,以减少阻塞的策略。

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

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

    编辑: 为了回应行动党的评论…

    “看来,这是我想的——没有办法绕过”停止世界“的那一部分。”

    这要看情况而定。在这种情况下 Java 6 Concurrent Collector 在标记根(包括堆栈)期间有两个停顿,然后标记/复制其他对象并行进行。对于其他类型的并发收集器,在收集器运行时使用读或写屏障来捕获收集器和应用程序线程在其他情况下会相互干扰的情况。我现在没有[琼斯]的拷贝,但我还记得有可能使“停止世界”的时间间隔变得微不足道…以更昂贵的指针操作和/或不收集所有垃圾为代价。

        2
  •  2
  •   Aaron    15 年前

    正确的做法是垃圾收集器必须暂停所有应用程序线程。通过使用并发收集器(它在不停止应用程序的情况下执行某些工作),可以通过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中管理垃圾收集的详细信息。

    对于Web应用程序,我不认为这是一个问题。由于用户请求应在很短的时间内完成,因此分配给服务的任何临时对象都不应退出年轻一代(前提是其大小适当),在那里它们被非常有效地清理。其他生命周期较长的数据(如用户会话)将停留更长时间,并可能影响在主要GC事件上花费的时间。

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

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

        3
  •  1
  •   redcalx    15 年前

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

    例如: A Parallel, Incremental and Concurrent GC for Servers(pdf)

    或者谷歌,比如“并发垃圾收集IBM”

        4
  •  1
  •   J D    14 年前

    当GC执行它的操作时,VM会阻塞所有正在运行的线程——或者至少当它压缩堆时。在现代的clr和jvm实现中(从2010年1月开始的生产版本)就是这样吗?

    Sun的Hotspot JVM和Microsoft的CLR都有并发的GCS,它们只在短时间内(以获取所有实时数据可从中访问的全局根的自一致快照)而不是整个收集周期内停止全球通信。我不确定它们的压缩实现,但这是非常罕见的。

    如果这确实是一种行为,那么像jboss和glassfish这样的重量级企业引擎如何保持始终如一的高TPS率呢?

    这些引擎的延迟比停止世界所需的时间要长几个数量级。此外,延迟被引用为,例如,第95个百分点,意味着延迟将只低于所引用时间跨度的95%。所以压缩不太可能影响引用的延迟。

        5
  •  0
  •   Matthew Wilson    15 年前

    有许多可用Java的GC算法,并不是所有的算法都阻塞了所有运行的线程。例如,您可以使用-xx:+useconcmarkswepgc,它与应用程序同时运行(用于永久生成的集合)。

        6
  •  0
  •   Paul Wagland    15 年前

    目前Java的垃圾回收的现状仍然涉及到“停止世界”的暂停。在Java6U14上引入的G1 GC大部分都是同时工作的,但是,当内存非常低时,它需要压缩堆,那么它必须确保没有人在它下面堆。这要求不允许进行任何其他操作。要了解关于g1 gc的更多信息,请查看 presentations from Sun .