最大化 AIX 上的 Java 性能,第 1 部分: 基础
http://www.ibm.com/developerworks/cn/aix/library/es-Javaperf/es-Javaperf1.html
最大化 AIX 上的 Java 性能,第 1 部分: 基础
这个由五个部分组成的系列提供了若干技巧和技术,这些技巧和技术通常用于优化 Java™ 应用程序,以便在 AIX® 上实现最佳的性能。其中还提供了有关每个技巧的适用性讨论。使用这些技巧,您应该能够快速优化 Java 环境,以适合应用程序的需要。
引言
存在若干可用于运行 AIX 的 IBM eServer pSeries 平台的性能优化工具。运行在 AIX 上 IBM 的 Java 实现还包含若干调整,其中大多数调整都有相当清楚的文档说明。尽管如此,IBM 支持团队仍然遇到了多种情况,其中性能优化工作受到这两组工具之间的分离影响。
本系列文章向您展示了如何结合使用 AIX 和 Java 工具,以最大化基于 AIX 的 Java 应用程序的性能。第 1 部分(“基础”)讨论了实现成功的优化工作的先决条件,并概述了可用于协助此类工作的工具。强烈建议您完整阅读此文,因为它可以在以后为您减少大量的麻烦。
本系列中的接下来三篇文章主要集中于性能优化的特定方面。第 2 部分(“速度需求”)讨论了如何改进执行速度和吞吐量。第 3 部分(“更多就是更好”)着眼于大小调整工作,并阐述了如何能够有利地操作内存。第 4 部分(“监视流量”)研究了作为性能优化目标的网络和磁盘 I/O。编写这三篇文章是为了便于快速查找,因此欢迎您将这些文章作为快速参考,而不是从头到尾地阅读。其中每篇文章还讨论了我们认为在实际工作中非常有用的一般技巧和调整。
第 5 部分(“参考资料和结论”)通过讨论有关此主题的其他信息源,从而结束了本系列。
请注意,本文仅限于 J2SE 信息;有关特定于 J2EE 的优化,请参考 J2EE 组件的配套文档。如果您在使用绑定 Java 的应用程序,应该参考应用程序文档以确保所做的任何更改不会影响应用程序功能。
开始之前
任何类型的优化工作都必须考虑到若干事项,其中有些事项在性质上是对立的。尽管每一项此类工作都是独特的,但是存在一些通用并且几乎始终有帮助的步骤。下面是在考虑性能优化前需要准备好的事项的简要清单。如果存在任何不能在优化开始之前完成的步骤,就应该存在这样做的充分理由。
迁移到最新版本
有关 AIX 上的最新可用 Java 版本列表,请参阅 IBM developer kits for AIX, Java technology edition。较新版本的 Java 包含通常具有重要意义的性能增强。例如,与以前版本相比,Java 1.4 具有强大得多的垃圾收集实现。
即使受到使用特定 Java 版本要求的约束,也应该迁移到最新的可用服务更新(Service Refresh,SR)。这是从功能和性能修复中获益的快速方法。此外,如果遇到任何类型的问题,您将需要迁移到最新的 SR 才能获得支持。对最新 SR 的升级的另一个示例是在 Java 1.3.1 已发布之后添加的诸如 -Xdisableexplicitgc
等开关,因此除非您迁移到特定的版本,否则无法使用这些开关。
本文着重以 Java 1.4 和 Java 1.3.1 环境为例,因为较旧的版本要么已经结束服务,要么很快就要结束服务了。由于同样的原因,我们将以 AIX 5L(明确地说是 AIX 5.1 和 AIX 5.2)环境为例,而不是 AIX 4.3.3 或更低版本。
如果应用程序的配置可行,您可能还希望考虑迁移到 64 位版本的 Java。这一主题超出了本系列的范围;除非特别说明,否则我们将把讨论限制到 32 位 Java。请继续关注 ESDD 上不久将推出的一篇有关 64 位 Java 的文章。
在优化之前修复问题
如果遇到诸如崩溃、内存泄漏或应用程序挂起等问题,那么您还没有为优化工作做好准备。这包括您禁用了 Just-In-Time (JIT) 编译器的部分或全部的情况。如果环境中指定了 JAVA_COMPILER 或 JITC_COMPILEOPT 环境变量,则应用程序可能已经遭受到性能损失(请注意,您也可以使用 JITC_COMPILEOPT 来优化应用程序性能。在开始性能优化之前,您应该已经修复了问题,无论是通过升级到最新的服务刷新,还是通过与 IBM Java Service 团队接洽。IBM developer kits - diagnosis documentation 上的 Java Diagnostics Guide 提供了有关如何调试 IBM Java 遇到的任何问题的出色建议。
验证您的环境
您通常不需要担心任何特定的环境设置(前一部分中提到的 JIT 设置,以及用于堆大小修改所需要的 LDR_CNTRL 设置,是一些值得注意的例外),因为 Java 启动程序会自己设置环境。但是,如果应用程序使用 JNI,则必须为 JNI 组件设置正确的环境。每个 Java 版本配套的 SDK 指南或自述文件都提供了需要设置为特定值的变量列表,这其中某个变量不匹配会导致性能和(或)功能问题。
您希望优化的是否为 Java?
虽然研究各个技巧并调整 Java 应用程序环境是个不错的主意,但是只有在消除其他瓶颈之后才能看到性能影响。例如,如果 Java 没有出现在消耗内存最多的前 5 个进程中,如果系统上的其他进程的 CPU 使用率保持在 100%,您对 Java 做出的更改很可能不会起作用。
它能运行得更快吗?
性能 这个措词是多方面的,每个角落都需要做出权衡决策。要从任何此类决策中排除猜测成分,必须充分了解预期行为,从而为您提供支持。您还必须拥有任由自己支配的良好定义的机制来测定所做的任何更改的影响。无论优化工作的规模如何,这里描述的步骤都将使优化工作更加高效。
了解您的应用程序特征
在开始优化应用程序之前,必须了解应用程序预期将如何工作。除了诸如客户机-服务器拓扑或图形用户界面(Graphical User Interface,GUI)应用程序等广义分类以外,您还应该了解应用程序代码在内部是如何工作以实现其尝试完成的任务的。举例来说,我们可以向您演示如何计算某次特定运行期间使用的 CPU 百分比值,但是对观察到的数字的解释则是每个应用程序所特有的。您应该能够区分“正常”和“异常”的观察行为,以便决定要优化什么对象。
请注意,您不需要访问 Java 源代码即可执行这些文档中描述的大多数优化。这并不意味着您应该将应用程序视为黑盒。您的应用程序是设计为快速完成工作并退出,还是继续运行很长一段时间(例如作为服务器)?它是在启动期间大量地分配内存,还是在启动时仅占用少量内存空间?它是否执行大量的回收,或者它是否占有已分配的对象?诸如此类的问题将决定您的优化工作。
选择优秀的测试套件
我们强烈建议准备某种方法来量化您已实现的收益。使用这其中任何工具的先决条件是存在一个可重复、可验证和可靠的测试套件,此套件允许您检查尽可能多的应用程序功能。记住,在某些情况下,调整运行时行为的一个方面可能会对另一部分造成负面影响。只有优秀的测试套件才使您能够了解运行时性能和内存占用空间(举例而言)之间的权衡。
建立基准
在对系统做出任何更改之前,应该花时间建立清楚和明确的方法来测定所做的任何更改的效果。此方法可以像使用“time”命令一样简单,或者更加精细,例如使用模拟一千个用户的脚本来测量响应时间。无论是哪种方法,用于测定性能调整效果的工作负载都应该足够多样化,以检查尽可能多的不同场景。除了任何类型的外部度量之外,我们建议使用 AIX 性能 PMR 数据收集工具 (PerfPMR)。
PerfPMR 工具实际上是 AIX 和其他服务团队使用的一个数据收集工具。它创建指定时间段内的系统快照,从而提供系统在该时间段内“做”什么的清楚指示。与单独运行每个 AIX 工具不同,您可以直接要求 PerfPMR 为您运行那些工具。由于创建这些快照的方法经过了良好的定义,您可以在优化周期中的不同时点创建多个快照,以跟踪优化进度。请注意,我们在本系列中提供了特定工具而不是 PerfPMR 的示例。
用于完成优化的工具
存在一组丰富的工具可用于监视 AIX 系统的所有方面。表 1 提供了各个工具的简述。这些工具可用于仅监视单个进程或监视整个系统。AIX 5L Performance Tools Handbook 和 Understanding IBM eServer pSeries Performance and Sizing 及其参考资料是了解下面提到的各个工具的很好起点。
表 1:AIX 上的系统监视工具
CPU | 内存子系统 | I/O 子系统 | 网络子系统 |
---|---|---|---|
vmstat iostat ps sar tprof |
vmstat lsps svmon filemon |
iostat vmstat lsps filemon lvmstat |
netstat ifconfig tcpdump |
后续的文章将对这其中每个工具进行简要介绍。还有一些工具无法归入某个特定类别,下面将对它们进行简要的讨论。
topas
topas 是一个有用的图形界面,可以为您提供系统上正在发生的事情的即时结果。当您不带任何命令行参数运行此工具时,屏幕将显示如下内容:
Topas Monitor for host: aix4prt EVENTS/QUEUES FILE/TTY Mon Apr 16 16:16:50 2001 Interval: 2 Cswitch 5984 Readch 4864 Syscall 15776 Writech 34280 Kernel 63.1 |################## | Reads 8 Rawin 0 User 36.8 |########## | Writes 2469 Ttyout 0 Wait 0.0 | | Forks 0 Igets 0 Idle 0.0 | | Execs 0 Namei 4 Runqueue 11.5 Dirblk 0 Network KBPS I-Pack O-Pack KB-In KB-Out Waitqueue 0.0 lo0 213.9 2154.2 2153.7 107.0 106.9 tr0 34.7 16.9 34.4 0.9 33.8 PAGING MEMORY Faults 3862 Real,MB 1023 Disk Busy% KBPS TPS KB-Read KB-Writ Steals 1580 % Comp 27.0 hdisk0 0.0 0.0 0.0 0.0 0.0 PgspIn 0 % Noncomp 73.9 PgspOut 0 % Client 0.5 Name PID CPU% PgSp Owner PageIn 0 java 16684 83.6 35.1 root PageOut 0 PAGING SPACE java 12192 12.7 86.2 root Sios 0 Size,MB 512 lrud 1032 2.7 0.0 root % Used 1.2 aixterm 19502 0.5 0.7 root NFS (calls/sec) % Free 98.7 topas 6908 0.5 0.8 root ServerV2 0 ksh 18148 0.0 0.7 root ClientV2 0 Press: gil 1806 0.0 0.0 root ServerV3 0 "h" for help
左下侧的信息显示了最活跃的进程;这里,Java 消耗了 83.6% 的 CPU。中间的右侧区域显示了总的物理内存(在此例中为 1 GB)和分页空间 (512 MB),以及正在使用的容量。因此您可以在单个屏幕中获得有关系统正在做什么的清楚概况,然后您可以基于其中显示的信息选择各个要集中的方面。
trace
trace 捕获带时间戳的系统事件的顺序流。trace 是用于观察系统和应用程序执行的宝贵工具。许多其他工具提供了诸如 CPU 和 I/O 利用率等抽象信息,而 trace 工具则帮助详述了有关事件在何处发生、哪个进程对事件负责、事件何时发生以及它们如何影响系统的信息。两个能够从 trace 提取信息的后期处理工具为 utld(在 AIX 4 中)和 curt (在 AIX 5 中)。这些工具提供了有关 CPU 利用率和进程/线程活动的统计信息。第三个后期处理工具是 splat,此工具表示“简单性能锁分析工具”(Simple Performance Lock Analysis Tool)。此工具用于分析简单锁在 AIX 内核和内核扩展中的锁活动。
nmon
nmon 是一个免费的软件工具,并提供许多与 topas 相同的信息,不过是将信息保存为 Lotus 123 和 Excel 格式的文件。此工具的下载站点为 http://www.ibm.com/developerworks/eserver/articles/analyze_aix/。所收集的信息包括 CPU、磁盘、网络、适配器统计、内核计数器、内存和“最忙”进程信息。
平台无关的 Java 性能监视
Java 虚拟机监视程序接口(Java Virtual Machine Profiling Interface,JVMPI)受 IBM Java 支持,并且对于性能监视的所有方面都非常有用。您可以使用第三方概要或使用 IBM Java 概要接口,以执行 Java 性能监视。有关更多详细信息,请参阅位于 IBM developer kits - diagnosis documentation 的 Java Diagnostics Guide 中的 -Xhprof
。有关特定于 AIX 上的概要分析的信息,您还应该参阅位于 IBM developer kits for AIX, Java technology edition 的自述文件/SDK 指南。例如,除非您设置了环境变量 AIXTHREAD_ENRUSG=ON
,否则在概要分析期间不会报告线程 CPU 时间。所有 Java 版本的自述文件/SDK 指南都对此作了文档记录。
也许最常用类型的 Java 性能监视是 verbosegc 日志。有关如何分析 verbosegc 日志的更多详细信息可以在 Fine-tuning Java garbage collection performance 中找到。虽然启用 verbosegc 跟踪的确会导致较小的性能影响,但是所获得的用于事后分析检查的优点无疑会胜过性能损失。Fine-tuning Java garbage collection performance 提到了如何基于 verbosegc 输出执行优化。
AIX 上的缺省 Java 行为
本部分描述各个设置的当前现状。这些设置在大多数情况下将会随时间推移而更改。SDK 的配套自述文件和 SDK 指南始终是此类设置的最新参考资料。
Java 使用了下列环境设置:
- AIXTHREAD_SCOPE=S
此设置用于确保每个 Java 线程一对一地映射到某个内核线程。可以在多种场合看到此方法的优点;一个显著的示例就是 Java 如何利用动态逻辑分区(Dynamic Logical Partitioning,DLPAR);当将新的 CPU 添加到该分区时,可以将某个 Java 线程调度到该 CPU 上。在正常情况下不应该更改此设置。
- AIXTHREAD_COND_DEBUG、AIXTHREAD_MUTEX_DEBUG 和 AIXTHREAD_RWLOCK_DEBUG
这些标志用于内核调试目的。这些标志有时可能设置为 OFF。如果不是这样,则关闭它们会提供很好的性能提升。
- LDR_CNTRL=MAXDATA=0x80000000
这是 Java 1.3.1 上的缺省设置,并控制如何允许大型 Java 堆增长。Java 1.4 基于所请求的堆来决定 LDR_CNTRL 设置。有关如何操作此变量的详细信息,请参阅 Getting more memory in AIX for your Java applications。
- JAVA_COMPILER
此设置决定将要使用的 Just-In-Time 编译器。缺省设置为 jitc,并指向 IBM JIT 编译器。可以将其更改为 jitcg,表示 JIT 编译器的调试版本;或者更改为 NONE,表示关闭 JIT 编译器(这样做在大多数情况下对性能来说绝对是最糟糕的)。
- IBM_MIXED_MODE_THRESHOLD
此设置决定 JVM JIT 在编译某个方法前该方法的调用次数。此设置视平台和版本而异;例如,对于 AIX 上的 Java 1.3.1,此设置为 600。
请注意,上述任何一个设置都不会覆盖现有的设置。例如,如果将 LDR_CNTRL=MAXDATA 更改为某个其他值,则会使用您指定的值而不是使用上面提到的缺省值。
IBM Java SDK 的配套自述文件/SDK 指南解释了任何 Java 本机接口(Java Native Interface,JNI)库都必须具有的环境设置。如果修改了该列表中指定的任何环境设置,您必须确保也使用相应的设置来生成 JNI 库。
总结
本文介绍了一些基本步骤,可作为开始优化工作的清单。接下来的三个部分将研究 CPU、内存、网络和磁盘 I/O 优化