分类: LINUX
2011-04-25 11:51:53
这一节包含了你调优Java应用可以采用的不同选择。基于这些选择的比较应该采用我们刚才讨论的统计学方法来进行。
这里是一些基本的调优准则,帮助你把不同的调优方法进行分类。
了解Java的动态调优机制在你开始调优Java启动的命令行参数之前,请注意,Sun HotSpotTM Java虚拟机具备了调整自身的特性。这种智能的自我调整称为“Ergonomics”。大多数具备2颗CPU和2G以上物理内存的机器都可以被看成是服务器级别(server-class)的机器。这意味着一下选项被缺省打开:
请注意,32位的Windows系统都缺省使用-client编译器,64位系统如果满足上面标准的话被认为是server-class机器。
尽管“Ergonomics”机制大大提升了许多应用“开箱即得”的性能,我们仍然需要对Java内存大小调整有足够的重视。
一个Java应用程序可以使用的最大的堆的大小取决于下面三个因素:
一个特定Java应用程序的堆的大小不可能超过进程数据模型的最大虚拟内存限制。对于一个32位的进程模型,虚拟内存的地址大小是4G,然而有些操作系统会限制到2G或3G。典型的堆的最大设定值是:-Xmx3800m (1600m - 2G的情况),具体的限制和应用本身也有关。对于64位进程模型,最大值基本上可以认为没有限制。对于一个特定机器上的Java应用,Java堆的大小永远不能设成物理内存的大小,因为额外的内存需要保留给操作系统,其他进程,甚至其他的Java虚拟机使用。使用太多的系统内存很容易引起虚拟内存和磁盘之间的交换,特别是在垃圾回收的时候,导致严重的性能问题。在那些有多个Java应用的环境,或者多个应用的环境里,这些进程的堆的总和不应该超过系统物理内存的大小。
另一个非常重要的可调参数是Young Generation(也就是NewSize)的大小。通常来讲,Young Generation的最大值是堆大小的3/8。
垃圾回收策略JavaTM平台提供了垃圾回收算法的选择。对于每一种算法存在有许多个可调参数。通常来说,下面的前两个是大型服务器应用最常用的选择:
通过适当地设置操作系统内存页面以及使用命令行参数-XX:+UseLargePages以及-XX:LargePageSizeInBytes,你可以从你的系统的内存管理系统中得到最好的效率。请注意,大的PageSize使我们能够更好地利用虚拟内存资源(TLB),但是这也使得Permanent Generation和Code Cache的尺寸变大,从而迫使你减小Java内存堆的大小。对于2MB或者4MB的内存页面问题或许不大,但是对于256MB的内存页,就值得仔细推敲了。
一个针对Solaris环境的例子就是选择libumem作为内存堆的分配器。为了体验libumem,你可以通过设置LD_PRELOAD环境变量来完成:
LD_PRELOAD=/usr/lib/libumem.so
LD_PRELOAD=/usr/lib/libumem.so java java-settings application-args
env LD_PRELOAD=/usr/lib/libumem.so java java-settings application-args通过pldd或者pmap命令,你可以确定libumem是否被使用。
并行的old generation收集java -Xmx3800m -Xms3800m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20
使用256MB内存页java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20 -XX:+UseParallelOldGC
比较激进的优化java -Xmx2506m -Xms2506m -Xmn1536m -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20 -XX:+UseParallelOldGC -XX:LargePageSizeInBytes=256m
使用有偏向性的锁策略java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20 -XX:+UseParallelOldGC -XX:+AggressiveOpts
低延迟和高吞吐java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20 -XX:+UseParallelOldGC -XX:+AggressiveOpts -XX:+UseBiasedLocking
监控和性能测量java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:ParallelGCThreads=20 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:SurvivorRatio=8 -XX:TargetSurvivorRatio=90 -XX:MaxTenuringThreshold=31
讨论监控(抽取一个程序运行的粗略统计数据)和性能测量(借助工具获得程序运行性能的细节)是需要单独的白皮书来论述的。这里借助一些例子来说明Java性能调优时可以用到的工具。
Java平台本身包含大量的监控工具,最流行的是JConsole和jvmstat
Java平台本身包含一些性能测量工具,最流行的是-Xprof Profiler和HPROF Profiler。一个基于JFluid技术的profiler插件被集成���了NetBeans环境里面。
NIO(New I/O)API针对内存映射文件和可扩展的网络操作,提供了更好的性能。通过使用NIO,那些频繁使用内存或网络的应用程序将得到巨大的性能提升。一个很好的例子就是Glassfish当中的Grizzly Web Container。
另一个影响程序性能的Java新特性是Concurrency Utilities。越来越多的应用跑在了多CPU多核的服务器上。为了充分利用这一特性,程序必须设计成多线程的。传统的多线程编程架构过于复杂,线程之间的交互容易引起错误。有了Concurrency Utilities之后,开发人员就拥有了一整套设计模块。使用它们开发多线程应用程序将变得事半功倍。