Chinaunix首页 | 论坛 | 博客
  • 博客访问: 537784
  • 博文数量: 150
  • 博客积分: 5000
  • 博客等级: 大校
  • 技术积分: 1705
  • 用 户 组: 普通用户
  • 注册时间: 2008-11-11 23:29
文章分类

全部博文(150)

文章存档

2011年(9)

2010年(25)

2009年(94)

2008年(22)

我的朋友

分类: Java

2008-11-24 13:58:23

  本文将介绍用于 iSeries 和 pSeries 上的 IBM JVM for Linux 的一些重要性能调优问题。在撰写这篇文章的时候,IBM 推出了 JDK 1.3.1 32-bit 和 JDK 1.4.2,但无论是 32 位还是 64 位风格的,都适用于 IBM iSeries 和 pSeries 上的 Linux。本文中提供的技巧可应用于 IBM iSeries 和 pSeries 上的 IBM JDK 1.3.1 和 JDK 1.4.2 for Linux,但是本文的特别针对目标是最新的 IBM JDK 版本 JDK 1.4.2。

本文将重点参考针对 JDK 1.3.1 和 JDK 1.4.2 的 IBM JVM Diagnostics Guides

这一节将介绍编写性能高效 Java 代码的一些通用准则,明确讨论如何避免对象创建和垃圾收集(GC),同时还将讨论 JNI、同步和数据结构。

只要有可能,应该避免创建对象,防止调用构造函数带来的相关性能成本,以及在对象结束其生命周期时进行垃圾收集所带来的成本。

考虑以下这些准则:
  • 只要有可能,就使用基本变量类型,而不使用对象类型。例如,使用 int,而不使用 Integer。
  • 缓存那些频繁使用的寿命短的对象,避免一遍又一遍地重复重建相同的对象,并因此进行 GC。
  • 在处理字符串时,使用 StringBuffer 而不使用字符串连接,因为字符串对象具有不可变的特性,并且需要创建额外的字符串对象,而这些对象最终必须经历 GC。
  • 避免过度对 Java 控制台进行写操作,降低字符串对象处理、文本格式化和输出带来的成本。
  • 实现数据库连接池,重用连接对象,而不是重复地打开和关闭连接。
  • 使用线程池(thread pooling)。避免不停地创建和删除线程对象,特别是在大量使用线程的时候。
  • 通过 System.gc() 调用避免在代码中调用 GC。GC 是一个“停止所有处理(stop the world)”的事件,它意味着除了 GC 线程自身外,其他所有执行线程都将处于挂起状态。如果必须调用 GC,那么可以在非紧急阶段或空闲阶段实现它。
  • 避免在循环内分配对象,这会使对象在 Java 堆上的存活时间超过必要的存活时间。

使用本机代码编写应用程序部分,特别是频繁使用的部分,并将之与 Java 链接,这样做通常是为了提高性能。不过,JVM 与本机代码之间的通信通常很慢,因此,太多的 JNI 调用可能会降低性能。只要有可能就应该将本机操作集合在一起,以减少 JNI 调用的数量。

使用 JNI 代码本地处理异常,尽管有时不可避免地会导致性能下降。在这种情况下,应该使用 ExceptionCheck() 函数,因为与 ExceptionOccurred() 相比较,它带来的计算开销更少一些。后者必须创建一个将引用的对象,以及一个本地引用。

为了减少 JVM 和操作系统中的争用,应该只在可行的情况下才使用同步方法。不要将同步方法放到循环结构中。

作为一条通用规则,在更简单的数据结构能满足需要的地方,应该避免使用更复杂的数据结构。例如,在可以使用数组的地方不要使用向量。使用最有效的方法搜索元素,并将元素插入数据结构中,比如说,在向量的结尾处添加和删除元素,以便获得更好的性能。

-O 优化标记编译 Java 代码。代码优化提供了以下几个好处:

  • 让代码变得模糊,使它更难以进行“逆向工程(reverse-engineer)”。
  • 极大地增强源代码的安全性。
  • 极大地减小 Java 程序的大小。
  • 提高运行时性能

目前,通过调整 SPINLOOP 变量和时间片值,可以显示可获得的最大性能。IBM_LINUX_SPIINLOOP 时间值是一个进程在锁定之前可以在某个繁忙的锁上自旋的次数。有三个 SPINLOOP 变量可进行调整(从 0 到 100 的数字):

  • IBM_LINUX_SPINLOOP1
  • IBM_LINUX_SPINLOOP2
  • IBM_LINUX_SPINLOOP3

在 16 路 LPAR 上执行的基准测试认为以下设置将是最佳设置:

  • IBM_LINUX_SPINLOOP1=96
  • IBM_LINUX_SPINLOOP2=85
  • IBM_LINUX_SPINLOOP3=85

与其他任何全局变量一样,需要在 shell 实例中设置这些变量,JVM 进程将会在这个实例中运行,因此,可以通过 JVM 将这些设置读取到全局变量表中。

在可以运行内核 2.4.19 的 SLES8 上,有一个用于设置 Linux 内核中时间片的最大值和最小值的选项。这些都是通过 sysctl 命令设置的。为了获得好的 Java 性能,极力推荐将 sysctl 值 sched_yield_scale 设置为 1。

CLASSPATH 变量应该在搜索路径的前面包含一些最常使用的 Java 库。对于 LIBPATH and LD_LIBRARY_PATH 变量,也应该这样做,以便获得最常使用的 JNI 共享库。


为了获得最佳性能,让运行 JVM 进程的用户拥有经过正确配置的用户设置是很重要的。这些参数可以设置成以下两种形式之一:

  • 暂时地,适用于通过 ulimit 命令登录 shell 会话期间。
  • 永久地,通过将一个相应的 ulimit 语句添加到由登录 shell 读取的文件之一(例如 ~/.profile),即特定于 shell 的用户资源文件;或者通过编辑 /etc/security/limits.conf。

建议设置成无限制(unlimited)的一些重要设置是:

  • 数据段长度:ulimit –d unlimited
  • 最大内存大小:ulimit –m unlimited
  • 堆栈大小:ulimit –s unlimited
  • CPU 时间:ulimit –t unlimited
  • 虚拟内存:ulimit –v unlimited

对于需要做许多套接字连接并使它们处于打开状态的 Java 应用程序而言,最好通过使用 ulimit –n,或者通过设置 /etc/security/limits.conf 中的 nofile 参数,为用户把文件描述符的数量设置得比默认值高一些。

“垃圾收集器”是影响 JVM 性能的最重要的 JVM 组件之一。关于 GC 和堆大小调优的一般性 IBM JVM 讨论(在针对 JDK 1.3.1 和 JDK 1.4.2 的 IBM JVM Diagnostics Guides 中)也可应用于 IBM JVM on Linux(包括 Linux on POWER),只是有一些 IBM JVM on Linux 特定的东西,后面会进行讨论。

最大堆大小是由 –Xmx 控制的,在 32 位 IBM JVM for Linux 上,可以将该值设置得比在 32 位 IBM JVM for AIX 上的更高一些,因为这两个操作系统的内存模式有所不同。如果没有指定 –Xmx 选项,则使用默认设置(即实际内存的一半,最小值是 16 MB,最大值是 512 MB)。

如果没用 –Xms 选项明确指定初始堆大小,那么该值是默认值 4 MB。有关 GC 和 Java 堆调优的更多信息,请参阅针对 JDK 1.3.1 和 JDK 1.4.2 的 IBM JVM Diagnostics Guides 中的“Debugging Performance Problems: JVM Performance”。“Understanding the Garbage Collector”和“Garbage Collector Diagnostics”这两章也值得一看。

就性能而言,JIT 是最重要的 JVM 组件。关于 IBM JVM JIT 的一般性讨论,请参阅 JVM Diagnostics Guide 中的“Understanding the JIT”小节。要获得关于 JIT 性能的 Linux 特定细节,请参阅“Linux Problem Determination”和“JIT Diagnostics”的 JIT 部分。

在 JVM Diagnostics Guide 的“Linux Problem Determination”一章中,详细地讨论了 IBM JVM for Linux 性能问题确定、JVM 监控和一些工具。

以下章节可能有其他的价值:

  • 追踪 Java 应用程序和 JVM。
  • 使用 JVM 监控接口(JVMMI)。
  • 使用可靠、可用和可服务的接口。
  • 使用 JVMPI。
  • 使用第三方工具。

以下是一些线程模型实现方面的详细说明,该实现将影响不同 Linux 发行版本上的 JVM 性能。请参阅 JVM Diagnostics Guide 中的“Linux Problem Determination”一章,以了解更多细节。

另一个要知道的问题是 Linux 上的线程浮点堆栈限制,正如 JVM Diagnostics Guide 的“Floating Stacks Limitation”小节中所讨论的那样。


GC
垃圾收集器
JDK
Java 软件包,包括 JRE 和一些开发工具
JIT
即时编译器
JRE
Java 运行时环境,无开发工具
JVMMI
Java 虚拟机监控接口
JVM
Java 虚拟机
JVMPI
Java 虚拟机分析接口
NPTL
本地 POSIX 线程库
OS
操作系统
RHEL AS
Red Hat Enterprise Linux 高级服务器版本
SLES
SUSE Linux 企业服务器
SR
服务刷新


  • 您可以参阅本文在 developerWorks 全球站点上的 英文原文

  • The Linux Documentation Project 是一个 Linux 文档知识库,其中包含关于各种软件、HOWTO 文档、FAQ 和其他更多信息的文档。

  • 构建更好的 GUI”(developerWorks, 2001 年 10 月)讨论了 Java 布局管理器的运用,以便获得更好的 GUI 总体设计。

  • Garfinkel 和 Spafford 合著的 Practical UNIX & Internet Security (O'Reilly & Associates,1996),是一个关于系统安全的所有方面(从用户管理到起草安全策略)的很好参考。



Nikolay Yevik 是 IBM eServer Solutions Enablement 团队的一名 Linux on POWER 技术顾问,有 6 年多的使用 C、C++ 和 Java 语言进行 UNIX 平台和性能开发的工作经验。他拥有石油工程和计算机科学硕士学位。您可以通过 yevik@us.ibm.com 与他联系。

阅读(788) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~