JVM 性能调整的一些基本概念(一)

2014-11-23 23:22:42 · 作者: · 浏览: 0
原文: http://www.freelamp.com/1017721999/index_html

由 徐永久 发表于 2002年04月02日 12:33。

本文是我在工作中调整 Solaris 8 上的 WebLogic 6.0SP2 中遇到诸多问题后,查阅相关资料而产生的一些概念,罗列出来,或许对您有所帮助。这并不代表,笔者推荐您使用 WebLogic 和 Solaris 的组合,相反,笔者欢迎相关 Tomcat 性能调整方面的心得。笔者在 Sun Tech Day 上和 Bea 公司的相关人员讨论后,认为 Bea 对 Open Source 和 Free Software 缺乏必要的远见。

另外,其中一些术语的翻译,是我自己的”创作“,我不知道别人是怎样翻译的。如果有不当的地方,希望指正。

堆( Heap)是 Java 程序的对象生活的地方,包含活的对象,死的对象以及剩余内存。

当对象不能被运行中的程序的指针所到达时,这些对象成为”垃圾“。

JVM 的堆大小决定了 VM 花费在收集垃圾上的时间和频度。

收集垃圾可以接受的速度与应用有关,应该通过分析实际的垃圾收集的时间和频率来调整。

如果堆的大小很大,那么完全垃圾收集就会很慢,但是频度会降低。

如果你把堆的大小和内存的需要一致,完全收集就很快,但是会更加频繁。

调整堆大小的的目的是最小化垃圾收集的时间,以在特定的时间内最大化处理客户的请求。

在基准测试的时候,为保证最好的性能,要把堆的大小设大,保证垃圾收集不在整个基准测试的过程中出现。

堆划分为两个区域:新生代和旧生代。

新生代又分为:Eden 和两片生存空间(survivor spaces)。其中保证有一片空间在任何时间是空的,当垃圾收集发生时, Eden 中的活的对象复制到下一片生存空间,对象就在生存空间之间复制,直到到达最大门限值(老化),然后复制到旧生代。

Eden 是新的对象分配的地方。

很多对象分配以后很快成为垃圾,这些对象称为具有 "infant mortality."

对象生存的时间越长,需要的收集时间也越长,因此,收集变慢。

你的应用建立和释放对象的速度决定了垃圾收集的频度。因此,在编程时,应注意使用对象的缓冲,而不是新建立对象。


大多数对象在新生代就已经死去,因此你能有效的调整垃圾收集。如果你能安排大多数对象的生存期小于一个收集时间,那么,垃圾收集是十分高效的。

错误的”代“配置会导致频繁的垃圾收集,影响系统性能。

如果系统花费很多的时间收集垃圾,请减小堆大小。

一次完全的垃圾收集应该不超过 3-5 秒。

一般说来,你应该使用物理内存的 80% 作为堆大小。


在最大工作负荷的时候,监视 WebLogic 的性能。
使用 -verbosegc 选项测量有多少时间和资源用于垃圾收集。

打开垃圾收集的详细信息输出以及重定向:

% java -ms64m -mx64m -verbosegc -classpath $CLASSPATH
-Dweblogic.domain=mydomain -Dweblogic.Name=clusterServer1
-Djava.security.policy==/bea/weblogic6x/lib/weblogic.policy
-Dweblogic.management.server=192.168.0.101:7001 -Dweblogic.management.username=system
-Dweblogic.management.password=systemPassword weblogic.Server >> logfile.txt

在 Solaris 系统上,采用下面的命令:

weblogic.Server > server.out 2>&1

Java HotSpot VM 选项

标准的选项在各种平台都已经有介绍:
http://java.sun.com/j2se/1.3/docs/tooldocs/win32/java.html
http://java.sun.com/j2se/1.3/docs/tooldocs/solaris/java.html
http://java.sun.com/j2se/1.3/docs/tooldocs/linux/java.html

以 -X 开头的选项都为非标准选项(并不能在所有的 VM 上实现),在后续的版本中可能会不通知而变更。

由于 -XX 选项需要特别的系统权限,因此不建议随便使用。

在 1.3.0 之前的版本, J2SDK 的 Solaris 版本带有一个 虚拟机的实现叫做 Exact VM(EVM),从 1.3.0 开始这个虚拟机被 Java HotSpot VM 所取代。

Java HotSpot VM 目前认识下面的 -X 选项:

-Xincgc 使用训练 GC
-Xnoincgc 不是用训练 GC(缺省)
-XX:MaxHeapFreeRatio= 最大堆剩余百分比(缺省 70)
-X:MinHeapFreeRation= 堆最小剩余百分比(缺省 40)
-Xint 只作解析 (不作 JIT 编译)
-XX:+UseBoundThreads 绑定用户级别的线程 (只针对 Solaris)
-Xmn 设置年轻一代的大小( young generation )(只对 1.4)

对象分配在 Eden,并且在这里死亡,当 Eden 满时,引起一个小的收集(minor collection),一些生存的对象被移动到旧生代,如果旧生代需要收集,则引起大收集(major collection ),这会比较缓慢。

如果 GC 成为瓶颈,那么需要指定代的大小,检查 GC 的详细输出,研究 GC 参数对性能的影响。

旧生代的收集采用 mark-compact 的方式,其中的一部分叫做”永久代“(permanent generation)很特别,他包括了 JVM 自身的所有反映数据(reflective data),例如类以及方法。

暂停时间的含义是应用因为垃圾收集而显示出来的短暂停顿。

吞吐量的含义是在一段比较长的时间内,没有用在垃圾收集的时间和总时间的百分比。

减少暂停时间的办法可以采用小的年轻代和增量收集,但是这以牺牲吞吐率为代价。


Footprint 是一批工作进程的集合,以页和缓冲行数计量,在物理内存有限或者有很多处理器的 系统里,footprint 可代表伸缩性。

Promptness 是对象死去的时间和内存变为可用时的时间差,在分布系统中(包括 RMI)需要考虑。

很大的新生代能提高吞吐率,但是牺牲了 footprint 和 promptness。

Solaris 的 footprint 可以采用 pmap 命令来查看。


[GC 325407K->83000K(776768K), 0.2300771 secs]
[GC 325816K->83372K(776768K), 0.2454258 secs]
[Full GC 267628K->8376