最大化 AIX 上的 Java 性能,第 2 部分: 速度需求
引言
这是由五部分组成的有关 AIX 上的 Java 性能优化的系列中的第 2 部分。强烈建议您在进一步继续之前阅读本系列中的第 1 部分(如果您还没有这样做的话)。
本文研究用于最大化系统执行速度和吞吐量的方法。对于涉及用户界面的程序,我们还将研究如何确保系统的响应能力保持在可接受的级别内。
您应该查看本文第一部分,以了解适用于大多数情况的一般技巧。我们还提供了对于 CPU 瓶颈检测和研究非常有用的工具的快速参考。下一部分将描述各种类型的应用程序以及如何优化它们。此讨论将利用您的应用程序知识来决定哪些技巧最适合您。第三部分将描述各种技巧。本文在结束时将讨论一下本系列中的下一篇文章。
CPU 瓶颈本文将讨论如何使您的应用程序更快或响应能力更高,或者同时实现这两个目的。
通过将实际与预期的性能数字进行比较,您通常可以确定应用程序是否运行得太慢。或者,应用程序的用户界面可能定期地定住,或者到应用程序的网络连接可能由于应用程序忙而超时。使用?topas?或?tprof?将显示 CPU 利用率是否达到 100%。您需要能够区分异常活动和大小设置不当的情况;如果您需要更快的 CPU 或更高规格的计算机,则没有多少调整空间可以执行。
作为第一步,您应该使用?topas?或其他类似工具来确定 Java 是否为最大的 CPU 用户。如果看到 Java 处在 CPU 用户列表中的较低位置,则执行特定于 CPU 的优化可能没有多大用处。我们在第 1 部分中提供了?topas?的简单概述。
理想的情况是应用程序的 CPU 利用率达到或高于 90%。如果您已经达到该阶段并且仍然对吞吐量不满意,也许是您使用的计算机的规格不够高。如果使用 DLPAR,可以尝试添加另外一个或两个 CPU 并测量差异。
本部分的其余内容将简单介绍一些常用的工具和如何检测特定于 Java 的问题。有关更多详细信息,请参见?AIX 5L Performance Tools Handbook?和?Understanding IBM eServer pSeries Performance and Sizing。
vmstat
vmstat?可用于提供有关系统的多种统计信息。对于特定于 CPU 的工作,可以尝试以下命令:
iostat可以使用?
iostat?获取?vmstat?所提供的相同 CPU 信息,此外还可以获取磁盘 I/O 等信息。ps
ps?是一个非常灵活的工具,用于确定正在系统上运行的程序和那些程序正在使用的资源。它显示有关系统上的进程的统计和状态信息,例如进程或线程 ID、I/O 活动、CPU 和内存使用。sar
sar -u -P ALL x y?可用于检查多个 CPU 之间的 CPU 使用平衡。如果使用情况分布不平衡,这可能指示应用程序没有线程化,并且您可能需要创建该应用程序的多个实例。下面的示例在一个达到 80% 利用率的双处理器系统上,相隔五秒钟进行了两次采样。tprof
tprof?是 AIX 遗留工具之一,可以提供每个 AIX 进程 ID 和名称的详细 CPU 使用情况分析。AIX 5.2 对其进行了完全的改写,下面的示例使用了 AIX 5.1 语法。您应该参阅?AIX 5.2 Performance Tools update:Part 3,以了解新的语法。调用此命令的最简单方法是使用:
特定于 Java 的技巧在几乎所有情况下(请参见相关技巧以了解例外情况),JIT 编译器都必须打开,因为这样导致的性能差异相当于执行字节代码与执行本机代码的差异。JIT 能够提供高达 25 倍的改进,因此它对 Java 来说是至关重要的性能组件。
垃圾收集也是另一个至关重要的组件,因此必须根据需要对其进行检查和调整。请注意,虽然启用 GC 跟踪(使用?
-verbosegc)具有轻微的负面影响,但是能够监视和分析堆的优点显然胜过负面影响。另一种考虑方式在于,良好状况的堆会最小化通过?-verbosegc?打印的信息量,因此通过调整堆,您还可以最小化执行附加跟踪的开销。基于特征的优化技巧
下面让我们看一下典型应用程序的不同特征。您应该定位到与您的应用程序类似的行为(无论是设计上的还是观察到的),并应用对应的技巧。
应用程序的长期性
IBM Java 旨在为诸如服务器代码等长期运行的应用程序提供更好的特征。如果由于某种原因要尝试运行持续时间不到 5 分钟左右的测试用例,您可能发现 IBM Java 为长期运行而做的准备会影响启动时间。如果应用程序的快速启动比长期运行更重要,请查看?技巧 CPU001:快速启动应用程序和?技巧 CPU004:完全去掉 GC。如果?技巧 CPU004:完全去掉 GC?不适用于您,可以改为考虑?技巧 CPU012:避免堆大小调整。在严格的情况下,如果您的测试用例是如此的短,以致 JIT 初始化也开销太大,您可能希望在关闭 JIT 的情况下进行测试。请注意,我们没有将禁用 JIT 作为一项独立的性能技巧提出来,这是因为,正如在上一篇文章中所提到的,这可能是影响应用程序性能的最糟糕的事情。
如果应用程序能够承受启动时间的轻微延迟,您应该参阅?技巧 CPU003:在第一次调用时编译所有内容和?技巧 CPU008:使用小型堆。对于具有明显的“初始化”和“运行”阶段的长时间运行的应用程序,技巧 CPU003:在第一次调用时编译所有内容是非常便利的。
交互级别
基于您的代码是否为计算密集型,JVM 的响应能力可以具有从非常关键到不相关的不同重要性。如果您要尝试优化的 JVM 在运行 GUI,则长时间的 GC 暂停将是不可接受的。与此同时,如果您在运行多个允许负载共享的 JVM 实例,或者如果正在执行批处理模式的处理,则长时间的暂停也许是可接受的。
对于无法承受长时间暂停的应用程序,请参见?技巧 CPU002:使用并发 GC、技巧 CPU004:完全去掉 GC、技巧 CPU007:禁用显式的 System.gc() 调用、技巧 CPU008:使用小型堆、技巧 CPU009:消除“标记堆栈溢出”和?技巧 CPU012:避免堆大小调整。技巧 CPU004 在大多数情况下仅适用于短时间运行的应用程序。请注意,必须将技巧 CPU008 与应用程序的内存特征结合起来考虑,因为如果应用不当,可能会带来相反的效果。
对于能够承受更长时间暂停的应用程序,应该考虑?技巧 CPU003:在第一次调用时编译所有内容。请注意,长时间暂停在大多数情况下都不是好事情,因此即使应用程序能够承受,也应该考虑并纠正该问题,因为您无法通过错误配置的 JVM 实例获得任何好处。
CPU 消耗
如果您在运行其线程数量超过已安装的 CPU 数量的应用程序,则观察到总体 CPU 利用率保持在 90% 或更高是很正常的,任何类型的后台处理都会损害您的应用程序的吞吐量。另一方面,如果您的应用程序是服务器,并且其线程在大多数时间都处于睡眠状态,只有在响应传入的请求时才会醒来,那么您也许能够使用后台处理来减小长时间 GC 暂停所导致的影响。
对于属于 CPU 密集型从而希望最小化后台处理的应用程序,可以考虑?技巧 CPU007:禁用显式的 System.gc() 调用、技巧 CPU008:使用小型堆和?技巧 CPU009:消除“标记堆栈溢出”。正如前面提到过的,您应该将?技巧 CPU008:使用小型堆与内存特征结合起来考虑。
对于非 CPU 密集型应用程序,强烈建议考虑?技巧 CPU002:使用并发 GC。这将通过减少 GC 周期到达时的总体暂停时间来获益。
定义良好的引用局域性
如果应用程序有一些经常执行的方法,而其他方法则很少执行,则?技巧 CPU003:在第一次调用时编译所有内容将是非常好的性能增强方法。
并行度
如果应用程序运行多个线程以完成工作,则会从具有大量 CPU 的系统中获益。对于动态分区,添加更多 CPU 会立即表现出改进,因为可以立即将 Java 线程调度到新添加的 CPU 上。技巧 CPU005:使用大量线程、技巧 CPU006:减少锁争用和?技巧 CPU011:超过 24 个 CPU 的系统讨论了可尝试的其他优化。
但是如果应用程序只有单个执行线程,则会受到单个 CPU 的处理能力的限制。在此情况下,您可能希望尝试?技巧 CPU002:使用并发 GC?和?技巧 CPU010:单 CPU 系统。如果您要尝试在某个系统上运行多个 JVM 实例(例如,在集群环境中),则?技巧 CPU010:单 CPU 系统特别有帮助。
一般技巧集合
下文将把 Java 的命令行参数(在 class/jar 文件名称之前指定)称为“开关”。例如,命令行“java -mx2g hello”具有单个开关“-mx2g”。
技巧 CPU001:快速启动应用程序
可以使用非标准开关?
-Xquickstart?缩短应用程序的启动时间。此开关将 JIT 优化级别降至最低,并且仅当适用的方法再次变得活动时才重新应用优化。对于其执行不是集中于少数方法的应用程序,这样做的结果是启动时间要快得多。请注意:由于多阶段的优化方法,此开关可能对长期运行的应用程序具有负面影响。请注意:
技巧 CPU002:使用并发 GC
可以指定“并发标记垃圾收集策略”(Concurrent Mark Garbage Collection Policy),以便减少 GC 周期引入的暂停时间量。这是使用?
-Xgcpolicy:optavgpause?开关来指定的。请注意:在某些情况下,CPU 密集型应用程序可能会在指定了并发标记的情况下表现出吞吐量下降。
技巧 CPU003:在第一次调用时编译所有内容(或选定的方法)
可以将环境变量 IBM_MIXED_MODE_THRESHOLD 设置为 0,从而关闭混合模式的解释器 (Mixed-Mode interpreter)。其结果是所有方法都将在第一次调用时进行 JIT 编译。将下面这一行内容添加到环境设置中,或者简单地在启动 Java 前运行此行命令:
总结本文介绍了如何使用 AIX 工具进行 Java 性能监视,并提供了可用来优化应用程序的 CPU 使用的常用调整列表。本系列中的下一篇文章将讨论 AIX 上的 Java 应用程序的内存调整。
参考资料
学习