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 策略的改变。在 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 策略。
首先,先对 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 策略中,比较重要的几个概念。
区域年龄,其实就是该区域经历垃圾回收的次数。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
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 示例
Balanced GC 策略能够提高运行在具有非统一内存访问架构(NUMA)的大型机上的应用程序的性能。
NUMA 用于 x86 和 IBM POWER 这样的多处理器系统上。在具用 NUMA 特性的系统上,每个一个处理器都拥有本地内存,它也可以访问分配给其它处理器的内存。但是访问本地内存的时间会短很多。NUMA 节点就是一组彼此靠近的处理器和内存。对内存节点内的内存的访问速度要快于节点外的内存。
Balanced GC 策略能够在 NUMA 节点上划分 Java Heap,对应用程序线程进行隔离,使得每一个线程拥有一个节点并在该节点上运行和进行对象分配。这样做能够增加访问本地内存的频率,从而提高应用程序的性能。
PGC 试图将对象移近引用其的对象和应用程序线程。这样做,应用程序线程的工作单元就可以物理上的靠近它实际运行的位置。
线程的隔离的目的就是为了提高的应用程序的性能。但是,有些情况下,线程隔离有可能会限制应用程序去使用所有的处理器能力。这个问题可能会带轻微的内存碎片,从而降低应用程序性能。您可以通过命令行参数 – Xnuma:none 关闭 NUMA 感知来验证这样的优化是不是会给您的应用程序带来不好的影响。
接下来,我们来看一下,在什么情况我们可以考虑使用 Balanced GC 策略。
通常情况下,如果您正在使用 Gencon GC 策略,性能不错,但是应用程序还是经历很长的全局垃圾回收时的暂停时间,并且这种情况频繁发生。在这种情况下,我们就可以考虑使用 Balanced GC 策略。
使用 Balanced GC 策略的前提条件:
- 前面提到了 Balance GC 策略只有在压缩列表 (compressd references) 特性被启用时才会生效。所以,这个策略只能在 64 位平台上使用。如果您的应用程序布署在 32 位或 31 位的硬件或操作系统上,或者您的应用程序要求加载 32 位或 31 位的本地库的话,那么您就不能使用该策略了。
- 根据平台的不同,Balanced GC 策略最大支持 28G 的 Java Heap。更多关于 compressd references 的信息,请查阅参考资源。该策略主要是用于优化大的 Heap。如果您的 Heap 小于 4G,那么与 Gencon GC 策略相比,您很可能看不到性能的改善。
那么,什么时候该考虑使用该策略呢
- 应用程序偶而地会经历不能接受的较长的全局垃圾回收暂停时间
Balanced GC 策略试图减少或是消除由于全局垃圾回收导致的长时间暂停,尤其是当全局压缩发生时。Balanced GC 策略通过在每一次回收时压缩部分 Heap,来实现以增量的方式减少内存碎片。通过前瞻性的以增量的方式来处理内存碎片,可以立即将连续的空闲内存放回到可分配的内存池中。Balanced GC 策略消除了有时候 Gencon GC 策略可能带来的工作的堆积。
- 大数组分配通常会导致全局垃圾回收、全局压缩或是两者同时发生
如果大数组分配频繁,即使有足够的总的空闲内存,也可能会导致垃圾回收的发生。Balanced GC 策略能够减少垃圾回收的频率以及总的暂停时间。增量的 Heap 压缩特性以及表述数据的内部的 JVM 技术,都使得在分配大数组时能够产生最小的影响。大数组指的是其大小大于整个 Heap 0.1% 的数组。
在以下这几种情况,使用 Balanced GC 策略也可能会带来好处
- 应用程序是多线程的,并且运行于具有 NUMA 特性的硬件上
当应用程序是多线程时,Balanced GC 策略就会利用 NUMA 硬件的特性。JVM 会将应用程序子线程与 UMNA 节点进行关联,然后将线程的对象分配到与之关联的内存中。根据使用模式的不同,Balanced 垃圾回收或者使对象保存在与之相关联的节点的内存中,或者将对象移动到与另一个节点相关的内存中。这个级别的隔离和关联可能会带来 Heap 碎片的增多,因此,可能会要求稍微大一点的 Heap。
- 应用程序不能够充分使用机器上所有的处理器内核
Balanced 垃圾回收有一个全局跟踪操作,能够破坏对象之间的环形相互引用和刷新整个 Heap 的信息,这个操作就是前面我们提到的 GMP。在进行这些操作时,JVM 会尝试去使用那些使用率低的处理器内核来在应用程程序时行时,来进行这些操作。这样做能够尽量减少这种操作可能需要的应用程序的暂停时间。
- 应用程序大量使用运态类加载(通常是由于大量使用反射机制造成的)
Gencon GC 策略能够卸载不使用的类以及类载器,但是只能在进行全局垃圾回收时。全局垃圾回收不经常进行,因为很少有对象能够存活的时间足够长并移动到年老代区域中,因此,可能会在本地内存中有大量的类以及类加载器的堆积。但是,Balance GC 策略能够在每次部分做 PGC 时,动态的卸载不使用的类以及类载器。这样一来,就可以减少这些类以及类加载器在内存中存留的时间。
本文向您介绍了 WebSphere Application Server V8 的 GC 策略的变化,并对新引入的 Balanced GC 策略进行了详细的介绍,希望能够对您今后使用 WebSphere Application Server V8 带来帮助。
学习
-
参考 WebSphere Application Server V8 信息中心,来了解更多信息。
-
Java 技术,IBM 风格 : 垃圾收集策略,第 1 部分
-
Java 技术,IBM 风格 : 垃圾收集策略,第 2 部分
-
Compressed Reference:IBM 信息中心技术支持
-
WebSphere Application Server 专题 为 WebSphere Application Server 开发人员准备的技术信息和资料,包括文章、教程、产品下载、在线支持手册等。
-
IBM developerWorks 中国 WebSphere 专区:为使用 WebSphere 产品的开发人员准备的技术信息和资料。这里提供产品下载、how-to 信息、支持资源以及免费技术库,包含 2000 多份技术文章、教程、最佳实践、IBM Redbook 和在线产品手册。
获得产品和技术
- 最受欢迎的 WebSphere 试用软件下载:下载关键 WebSphere 产品的免费试用版。
- IBM developerWorks 软件下载资源中心:IBM deveperWorks 最新的软件下载。
- IBM developerWorks 工具包:下载关键 WebSphere 最新的产品工具包。
讨论
- 加入 developerWorks 中文社区,developerWorks 社区是一个面向全球 IT 专业人员,可以提供博客、书签、wiki、群组、联系、共享和协作等社区功能的专业社交网络社区。
- 加入 IBM 软件下载与技术交流群组,参与在线交流。
李明慧: 2007 年加入 IBM,先是在 IBM 中国软件开发中心 Data Studio 团队工作从事 InfoSphere Warehouse Administration Console 的功能测试工作。后转到 WebSphere 应用服务器系统测试部组工作,曾在 developerWorks 发表《将 DB2 DWE 9.1.X 迁移到 DB2 Warehouse 9.5 》、《 InfoSphere Warehouse SQL 仓储命令行接口》以及《 Linux 下利用 squid 反向代理提高网站性能》《 InfoSphere Warehouse Administration Console 的对比介绍》,《 SQL 语句性能调优 - 初级篇》。