IBM® WebSphere® Application Server 是 IBM 旗舰应用服务器产品,在 2011 年 6 月 17 日正式发布了 V8 版本。在 WebSphere Application Server V8 中有引入了很多新特性,例如,支持新的编程模型和新的标准,简化的安装过程,安全和性能方面的提高,以及服务器管理方面的新特性等等。
本文将向您介绍 WebSphere Application Server V8 在 GC 策略方面的一些变化。
WebSphere Application Server V6.1 和 V7 的用户,肯定都知道 WebSphere Application Server 的 GC 策略选项有
- -Xgcpolicy:optthruput
- -Xgcpolicy: optavgpause
- -Xgcpolicy: gencon
- -Xgcpolicy: subpool
在 WebSphere Application Server V8 中 GC 策略有了一些变化或并且还有新增的特性。接下来,就将向您详细介绍。关于上述 GC 策略的介绍,您可以阅读参考资源中的相关文章来了解相关信息。
GC 策略的改变
默认 GC 策略的改变。在 WebSphere Application Server V8 之前,默认的 GC 策略是 optthruput。对于吞吐量比短暂的 GC 停顿时间更重要的应用程序,通常会采用这种 GC 策略。每当进行垃圾回收时,应用程序都会停顿。在 WebSphere Application Server V8 中,默认的 GC 策略变成了 gencon。这种 GC 策略以不同的方式处理短期存活对象和长期存活对象。采用这种策略,对于具有很多短期存活对象的应用程序会表现出更短的暂停时间,但是仍然能产生很好的吞吐量。
GC 策略 subpool,在 WebSphere Application Server V8 中,已经是不被推荐使用的了,如果使用这个 GC 策略的话,就等同于使用 optthruput。
在 WebSphere Application Server V8 中引入新的 GC 策略 balanced。这种 GC 策略目的是用于内存大于 4G 的环境,并且这个 GC 策略选项仅在 64 位平台上才有。下面就将向您详细介绍这种新引入的 GC 策略。
新的 GC 策略 Balanced
首先,先对 Balance GC 策略进行一个总体的介绍,然后再您介绍该策略比较重要的几个概念,最后会告诉您在哪些场合下,我们适合用该策略。
在 Balanced GC 策略中 Java Heap 采用的是基于区域的布局方式。这些区域都是独立管理的,这样可以避免较大 Heap 上的停顿时间。而且也可以利用现代服务器硬件 非统一内存访问架构(Non-Uniform Memory Architecture)所带来的好处。
前面提到Balanced GC 策略的目的是用于内存大于 4G 的环境,并且只在 64 位平台上才有提供。您需要在命令行指定 -xgcploicy:blanced 来启用这个策略,同时还需要指定 -Xcompressedrefs 参数,因为 Balanced GC 策略只有当压缩列表 (compressd references) 特性被启用时才会生效。
采中 Balanced GC 策略,Java Heap 会被分为成千上万个被称为“区域(region)”的等份。每一个区域都是独立的进行垃圾回收,这使得回收器可以只关注某些区域,通过对这些区域的处理,可以以最少的处理来获得最大量的内存回收。对象由回收器分配到其选择的一组空闲的区域中,这些区域被称为 "eden space"。当这些 eden space 被占满之后,回收器会将应用程序停止,然后进行“部分垃圾回收(Partial Garbage Collection PGC)”。这个回收也可能会包括其它的非 eden space 的区域,如果回收器觉得这些区域也是值得回收的,它就会将这些区域也一同进行回收。当回收工作结束之后,应用程序线程继续,分配新的 eden space,直到这部分区域被占满。上述垃圾回收操作在整个应用程序的生命周期内进行。
有时候,回收器也会进行全局标记阶段(Global Mark Phase GMP)来寻找更多的能被回收的内存。因为 PGC 在每次垃圾回收时,只是处理一部分的 Heap 区域,一些未被引入的对象很可能还会存在于 Heap 中。这个问题,就如同在并发回收中的 "floating garbage" 问题一样。GMP 作用于整个 Java Heap,它能够辨别出那些已经长时间不活动的对象,并对其进行标记,并将这些对象回收。
接下来,我们来看一下,在 Balanced GC 策略中,比较重要的几个概念。
区域年龄 (Region Age)
区域年龄,其实就是该区域经历垃圾回收的次数。Java Heap 中每一个区域都会被记录年龄。与分代垃圾回收一样,Balanced 垃圾回收器也会记录 Java Heap 中对象的年龄。分代垃圾回收方式下,分代垃圾回收器记录每一个对象的对象年龄。它将 Heap 分成两代,分别为年轻代(new)和年老代(tenure),新生成的对象会都首先放在年轻代,在年轻代中经历了 N 次垃圾回收还仍然存活的对象,就会被入到年代中。然而,在 Balanced GC 策略中,垃圾回收器是对每个区域记录年龄,分成 24 个可能的代。年龄为 0 的区域,也被称为 "eden space",包含有最新分配的对象。年龄最大的区域,是所有最终长期存活的对象所处的区域。PGC 必须收集年龄为 0 的区域,但是也可以增加任何其它需要收集的区域,而无需考虑其年龄。
图 1. 基于区域的 Java Heap 中未被使用的区域以及有年龄区域示例
注意:从上图我们可以看到,具有相似年龄的区域并不要求是连续。
Partial Garbage Collection (PGC)
PGC 通过 Copy-Forward 或是 Mark-Compact 操作来回收 Java Heap 上的内存。
当 eden space 满了之后,应用程序暂停,在分配新的区域做为新的 eden space 之前,PGC 进行垃圾回收,然后,应用程序继续运行。PGC 是 "stop-the-world" 操作,这意味着在 PGC 进行垃圾回收时,所有的应用程序线程都是暂停的。PGC 可以对在 Heap 上任何的一组区域进行垃圾回收,但是这些区域里一定要包含用于分配内存的 eden space。其它的区域可以根据像年龄、空闲内存以及内存碎片等等这样的因素来加入到内存回收集中。
因为 PGC 只是关注于 Heap 的一个子集,所以该垃圾回收操作很可能会错过回收在某一个区域中的需要回收的对象。这个问题可以通过接下来将要介绍的 Global Mark Phase (GMP) 来解决。
在下面这个例子中,区域 A 和区域 B 每个都包含一个对象,它们彼此互相引用,即它们中的任一个只能通过另外一个才能被访问。
图 2. 相互引用的对象示例
如果只有 A 或 B 被回收,这个环的一半使另外一个对象还存活着。然而,GMP 能够看到这样的不能访问的对象,并对其进行标记。
Balanced GC 策略在 PGC 操作中使用 Copy-Forward 回收器或是 Mark-Compact 回收器。通常情况下,该策略倾向于使用 Copy-Forward 回收器,但是如果 Heap 太满了的话,也可以部分的或是全部的改用 Mark-Compact 回收器。您可以通过查看详细垃圾回收日志来查看使用哪个回收策略。
Copy-Forward 操作
下面这个例子向您展示了 PGC 操作采用 Copy-Forward 策略,其中灰色区域代表了存活象,白色区域代表示被使用的。
图 3. 未进行 Copy-Forward 操作之前的 Java Heap
图 4. Copy-Forward 操作进行中的 Java Heap,其中箭头代表了对像的移动
图 5. 进行 Copy-Forward 操作之后的 Java Heap
Mark-Compact 操作
下面的示例向您展示了 PGC 操作采用 Mark-Compact 策略,其中灰色区域代表了存活象,白色区域代表示被使用的。
图 6. 未进行 Mark-Compact 操作之前的 Java Heap
图 7. Mark-Compact 操作进行中的 Java Heap,其中箭头代表了对象的移动
图 8. 进行 Mark-Compact 操作之后的 Java Heap
Global Mark Phase (GMP)
GMP 作用于整个 Java Heap,搜索,标记已废弃的对象,以便对它们进行垃圾回收。
GMP 在 PGC 操作之间独立的进行。尽管 GMP 也是像 PGP 那样增量的运行, GMP 却只进行标记操作。但是这个标记操作却是作用于整个 Java Heap 而不会仅局限于区域的级别。因为作用于整个 Java Heap,GMP 能够发现比 PGP 更多的已被废弃的对象。GMP 不会在一次 "stop-the-world" 操作中开始并且结束,这样就可以避免一些已被废弃的对象仍被当作存活的,成为 "floating garbage"。
GMP 能够与应用程序线程并行的进行一些操作。这个并行操作完全依赖于后台线程,这样做的话,就可以利用空闲的处理器来完成工作,而不必关心应用程序以多快的速度来分配内存。
当 GMP 完成这后,PGP 存留下来的对象就会被替换。下一次 PGP 作用于 Java Heap 上最新的对象。
图 9. 经过 GMP 之后存活的对象只是经过 PGC 之后存活对象的子集
当 GMP 为 PGC 操作替换数据后,下一次 PGC 将使用这个更小的集合进行更剧烈的回收。这个过程使得 GMP 能够清理掉 GMP 集合中所有存活对象。
图 10. GMP 进行替换数据后 Java Heap 示例
NUMA 感知性
Balanced GC 策略能够提高运行在具有非统一内存访问架构(NUMA)的大型机上的应用程序的性能。
NUMA 用于 x86 和 IBM POWER 这样的多处理器系统上。在具用 NUMA 特性的系统上,每个一个处理器都拥有本地内存,它也可以访问分配给其它处理器的内存。但是访问本地内存的时间会短很多。NUMA 节点就是一组彼此靠近的处理器和内存。对内存节点内的内存的访问速度要快于节点外的内存。
Balanced GC 策略能够在 NUMA 节点上划分 Java Heap,对应用程序线程进行隔离,使得每一个线程拥有一个节点并在该节点上运行和进行对象分配。这样做能够增加访问本地内存的频率,从而提高应用程序的性能。
PGC 试图将对象移近引用其的对象和应用程序线程。这样做,应用程序线程的工作单元就可以物理上的靠近它实际运行的位置。
线程的隔离的目的就是为了提高的应用程序的性能。但是,有些情况下,线程隔离有可能会限制应用程序去使用所有的处理器能力。这个问题可能会带轻微的内存碎片,从而降低应用程序性能。您可以通过命令行参数 – Xnuma:none 关闭 NUMA 感知来验证这样的优化是不是会给您的应用程序带来不好的影响。
添加新评论1 条评论
2013-04-11 09:44