优化 Java 垃圾收集器改进系统性能

合集下载

基于嵌入式Java虚拟机的垃圾收集优化算法

基于嵌入式Java虚拟机的垃圾收集优化算法

其 中, 表示全收集的回收率 ;T表 示全 收集花费 时间;M
表示整堆空间 ;r 表示 轻量收集 的回收率 ;, 表示轻量 收集花
费时间 ;m表示新生代空间。令两式相等得 :
m :M R t /
收集 ,有效提高了收集效率 ,同时 ,由于垃圾收集过程是基
于存活对象的拷贝 ,避免了内存碎片 的产生 。但 是分代垃圾 收集算法仍存在一些缺陷 : () 1 虚拟机运行不同的应 用时,拥有较长生命 期的对象所 占用 内存空间不同。若为 旧生代预留空间过多 ,将会导致 内 存浪费 ;若预留空间过少 ,将导致 生命期较长的对象 不能被
D0I 1.9 9 .s.0 03 2 . 1.70 6 : 03 6 /i n1 0 .4 82 20 .1 js 0
1 概述
随着人们对手机、P A、机顶盒 等嵌 入式设备 多功能性 D 要求越来越高 ,Jv aa虚拟机(aaVr a Mahn, V 逐渐 Jv iu l cie J M) t 成为嵌入式设备的核 心组成部分I。Jv l a a虚拟机提供 了垃圾 j 收集机制 ,将程序员从繁重 的内存管理工作中解脱 出来 ,同
[ tat hs a e n l e n mpo e e eai a abg ol t n a rh pooe no t ao l r l sr c]T i p pra a zsad i rv steg nrt nlgraec l c o loi m, rp ssa pi zt n a oi m o abg Ab y h o ei g t mi i g t frG ra e h
的效率较高 ,但会导致内存碎 片。 虽然 目前有很多垃圾收集优化 算法 ,但是大多都是针对 桌面系统,为使其适用于资源 受限的嵌入式 Jv 环境 ,需要 aa

Java代码优化提升性能与可维护性

Java代码优化提升性能与可维护性

Java代码优化提升性能与可维护性在软件开发中,代码优化是提高应用程序性能和可维护性的重要环节之一。

而对于Java开发者来说,优化Java代码是必不可少的任务。

本文将分享一些提升Java代码性能和可维护性的经验和方法。

一、使用合适的数据结构和算法在编写Java代码时,选择合适的数据结构和算法是提升性能的重要一环。

例如,使用ArrayList而不是LinkedList可以大幅度提高数据的访问效率;使用HashMap而不是TreeMap可以快速实现键值对的查找和插入操作。

另外,对于频繁进行查找和插入操作的场景,可以考虑使用哈希表或者红黑树等高效的数据结构。

同时,深入了解不同的排序算法,选择最适合实际情况的排序算法,也能帮助提高代码的性能。

二、避免过多的对象创建和销毁Java的垃圾回收机制会自动回收不再使用的对象,但频繁地创建和销毁对象会给垃圾回收器带来额外的负担,导致性能下降。

因此,在编写Java代码时,应该合理使用对象池、缓存或者复用对象的方式,减少不必要的对象创建和销毁。

同时,在循环中尽量避免在每次迭代中创建对象,可以将对象的创建放在循环外部,以减少对象的重复创建,提高代码性能。

三、使用合适的数据类型和APIJava提供了丰富的数据类型和API,正确选择和使用合适的数据类型和API可以极大地提高代码的性能和可维护性。

例如,对于整数运算,使用int类型而不是Integer类型可以避免自动装箱和拆箱的开销;对于字符串拼接,使用StringBuilder而不是String可以减少字符串对象的创建。

此外,了解并合理使用Java提供的各种集合类,选择最适合实际场景的集合类,也是优化Java代码性能的重要一环。

四、合理进行代码分割和模块化将复杂的代码分割成模块化的功能单元,可以提高代码的可维护性和可读性。

通过良好的模块化设计,可以使代码更易于理解、测试和调试。

同时,模块化还可以使多人协作开发更加高效。

在Java中,可以使用包和类的方式来实现代码的模块化,将相关的功能封装到不同的类中,并通过包的方式进行组织和管理。

Java中的性能调优技巧

Java中的性能调优技巧

Java中的性能调优技巧在Java中进行性能调优是提高程序执行效率和响应速度的关键步骤之一。

通过优化代码、使用高效的数据结构和算法,以及合理配置Java虚拟机(JVM)参数,可以显著改善Java应用程序的性能。

本文将介绍几种常用的Java性能调优技巧,帮助开发者针对不同场景优化Java应用程序。

一、优化代码1. 减少创建对象的次数:频繁创建对象会占用大量内存和CPU资源。

在需要使用对象时,尽量重用已有对象,避免过多的对象创建和销毁操作。

2. 使用StringBuilder代替String拼接:String的拼接会创建新的String对象,而StringBuilder可以避免这种性能损耗。

尤其在循环中进行大量字符串拼接时,使用StringBuilder性能更佳。

3. 避免使用过时的方法和API:及时了解JDK的更新和改进,避免使用已废弃的方法和API,以确保代码在性能上得到最新的优化。

4. 尽量使用局部变量:局部变量的生命周期短,会被垃圾回收机制释放。

相比之下,全局变量的生命周期长,会占用更多的内存。

5. 避免过多的同步操作:过多的同步操作可能导致线程的竞争和等待,从而降低程序的执行效率。

可以考虑使用更轻量级的同步方式,如使用ConcurrentHashMap替代Hashtable。

二、使用高效的数据结构和算法1. 使用合适的集合:在选择集合类时,考虑元素的增删操作频率、是否需要排序等因素。

例如,如果需要频繁进行元素的增删操作,可以选择LinkedList;如果需要排序,可以选择TreeSet或TreeMap。

2. 使用合适的算法:选择合适的算法可以大幅度提高程序的性能。

例如,对于大量数据的排序操作,可以采用快速排序算法;对于查找操作,可以选择二分查找等高效算法。

三、合理配置JVM参数1. 设置合适的堆内存大小:通过调整-Xmx和-Xms参数,可以配置JVM的最大堆内存和初始堆内存。

尽量将堆内存设置为真实需求的两倍,避免频繁的垃圾回收。

Java垃圾收集机制及性能调节

Java垃圾收集机制及性能调节

Java垃圾收集机制及性能调节
曾天慧;於时才;董荣辉
【期刊名称】《计算机工程与设计》
【年(卷),期】2006(27)17
【摘要】Java技术通过自动的垃圾收集来管理内存的回收,降低了编写代码的复杂程度,减小了系统中潜在的不安全因素.针对众多开发人员在实际应用中未能充分发挥垃圾收集机制优势的情况,基于对Java虚拟机中垃圾收集机制及其实现的分析,提出了在具体应用中对垃圾收集算法进行选择和对Java虚拟机相关参数进行调节的方法.实验表明,该方法使得垃圾收集对系统性能的负面影响最小化,从而提高了系统的性能和效率.对开发人员具有一定的参考价值.
【总页数】4页(P3242-3244,3247)
【作者】曾天慧;於时才;董荣辉
【作者单位】兰州理工大学,计算机与通信学院,甘肃,兰州,730050;兰州理工大学,计算机与通信学院,甘肃,兰州,730050;兰州理工大学,计算机与通信学院,甘肃,兰州,730050
【正文语种】中文
【中图分类】TP302.7
【相关文献】
1.小议Java 虚拟机的垃圾收集机制 [J], 姚晔;宋诗瑶
2.Java虚拟机垃圾收集器的性能分析与调节 [J], 吕爱民;何钦铭
3.Java垃圾收集机制的研究 [J], 孔凡良
4.浅谈JAVA中的垃圾收集机制 [J], 刘敬伟
5.关于Java垃圾收集机制的负面影响分析 [J], 刘远军;董峰
因版权原因,仅展示原文概要,查看原文内容请购买。

Java中性能优化的35种方法汇总

Java中性能优化的35种方法汇总

Java中性能优化的35种⽅法汇总前⾔对程序员们来说,代码优化是⼀个很重要的课题。

可能有些⼈觉得没⽤,⼀些细⼩的地⽅有什么好修改的,改与不改对于代码的运⾏效率有什么影响呢?这个问题我是这么考虑的,就像⼤海⾥⾯的鲸鱼⼀样,它吃⼀条⼩虾⽶有⽤吗?没⽤,但是,吃的⼩虾⽶⼀多之后,鲸鱼就被喂饱了。

代码优化也是⼀样,如果项⽬着眼于尽快⽆BUG上线,那么此时可以抓⼤放⼩,代码的细节可以不精打细磨;但是如果有⾜够的时间开发、维护代码,这时候就必须考虑每个可以优化的细节了,⼀个⼀个细⼩的优化点累积起来,对于代码的运⾏效率绝对是有提升的。

代码优化的⽬标是:1、减⼩代码的体积2、提⾼代码运⾏的效率代码优化细节1、尽量指定类、⽅法的final修饰符带有final修饰符的类是不可派⽣的。

在Java核⼼API中,有许多应⽤final的例⼦,例如ng.String,整个类都是final的。

为类指定final修饰符可以让类不可以被继承,为⽅法指定final修饰符可以让⽅法不可以被重写。

如果指定了⼀个类为final,则该类所有的⽅法都是final的。

Java编译器会寻找机会内联所有的final⽅法,内联对于提升Java运⾏效率作⽤重⼤,具体参见Java 运⾏期优化。

此举能够使性能平均提⾼50%。

2、尽量重⽤对象特别是String对象的使⽤,出现字符串连接时应该使⽤StringBuilder/StringBuffer代替。

由于Java虚拟机不仅要花时间⽣成对象,以后可能还需要花时间对这些对象进⾏垃圾回收和处理,因此,⽣成过多的对象将会给程序的性能带来很⼤的影响。

3、尽可能使⽤局部变量调⽤⽅法时传递的参数以及在调⽤中创建的临时变量都保存在栈中速度较快,其他变量,如静态变量、实例变量等,都在堆中创建,速度较慢。

另外,栈中创建的变量,随着⽅法的运⾏结束,这些内容就没了,不需要额外的垃圾回收。

4、及时关闭流Java编程过程中,进⾏数据库连接、I/O流操作时务必⼩⼼,在使⽤完毕后,及时关闭以释放资源。

WebSphere性能调优-垃圾收集器

WebSphere性能调优-垃圾收集器

WebSphere 性能调优-垃圾收集器基于 WebSphere 构建的企业应用,时常会出现性能问题,在严重的情况下还会提示出内存溢出,这是 一件很让人恼怒的事情。

在 WebSphere Application Server(Was)运行的时候,内存溢出,会生成大量的 溢出文件,如 Javacore, Heapdump 等文件,占用了大量的磁盘空间。

在这种情况下,时常会出现一连串的 系统问题,如部署在 Was 的所有应用服务都报错,Was 连控制台也无法访问等。

为解决问题,我们通常会选择重新启动整个 Was 或者服务器,然后分析运行日志 SystemOut.log、yst emErr.log、ative_stdout.log、native_stderr.log 和系统内存溢出的时候产生的 Javacore、Heapdump 文件来寻找出问题。

那么,为什么会出现内存溢出呢? 应用服务器在运行过程中需要创建很多对象,而在应用服务器的堆空间大小有限的情况下,请求进程 不断申请空间来创建与存放对象,在达到上限时而服务器又没能释放出空间来处理申请空间的请求就会出 现内存溢出情况。

这就像吹气球,当气球中的气体到达一定程度时,气球就会被撑爆。

(32 位的 JDK 的 J vm 堆空间分配最大支持 1.5G 的大小,超过则无法正常启动。

而 64 位的 JDK 堆大小分配无限制,其大小受 到服务器的内存限制。

)通常在投入生产的系统中,出现溢出一般都是对象分配不合理导致的。

在此,让我们先了解下 Java 世界里,对象与对象管理是怎么一回事。

在 Java 的体系中,所有的类作为一个对象(包括 Jdk 本身提供的类,应用中由开发人员编写的类), 都是直接或者间接继承了 ng.object 产生的。

这些类被创建的时候都会向 Jvm 堆申请一定的内存空 间存放,因此在 Jvm 堆空间里会存放各式各样的对象,有的是静态类型,有的是私有类型等等,而这些对 象都是通过垃圾收集器进行管理的。

如何提高Java程序的性能

如何提高Java程序的性能随着软件开发的不断发展,性能成为了一个非常重要的关键词。

而对于Java程序来说,性能的好坏直接影响着程序的运行速度和效率。

因此,优化Java程序的性能已经成为了程序开发人员的必修课程,本文将介绍一些提高Java程序性能的常用技术和方法。

1.使用最新版本的JDK在使用Java进行程序开发时,版本选择也能对性能产生很大的影响。

因此,程序开发人员应该选择最新的JDK版本。

JDK的新版本中,JVM在很多方面都已经有了很大的优化,这可以有效地提高程序的性能。

2.避免频繁的GCJava是一门垃圾回收语言,频繁的GC会影响程序的性能。

因此,在编写程序时,应该避免频繁的对象创建,尽量复用同一对象。

如果对象必须被创建,可以考虑使用对象池等技术。

3.尽量少使用全局变量和静态变量全局变量和静态变量的存在会增加程序的内存消耗,而且这些变量往往需要在多线程环境下使用,会增加锁的开销,从而降低程序的性能。

因此,在编写程序时,尽量少使用全局变量和静态变量。

4.尽量使用局部变量和数组局部变量在方法结束时会自动释放内存,而且局部变量的生命周期不会影响程序的其他部分,这可以有效地提高程序的性能。

另外,Java中的数组也比较高效,因此,在需要存储大量数据的时候,建议使用数组。

5.使用高效的算法和数据结构在编写Java程序时,选用高效的算法和数据结构也能有效地提高程序的性能。

例如,在需要对数据进行查找和排序时,可以选择快速排序、归并排序等高效的算法,或者选择HashMap等高效的数据结构,从而提高程序的性能。

6.避免使用String的"+"运算符拼接字符串在Java中,字符串的"+"运算符拼接字符串是一种比较常见的做法。

然而,这种做法效率比较低,因为每次拼接字符串都会重新创建一个新的字符串对象,从而消耗大量的内存和CPU资源。

因此,在编写程序时,应该避免使用String的"+"运算符拼接字符串,而是应该使用StringBuilder或者StringBuffer。

Java语言中的JVM优化技巧

Java语言中的JVM优化技巧Java虚拟机(JVM)是Java语言的核心部分,它是一种运行在操作系统之上的虚拟计算机,负责Java程序的编译、解释和执行。

由于JVM是Java语言的运行环境,JVM的性能对于Java程序的性能也具有至关重要的影响。

因此,对于Java程序的开发者来说,优化JVM是非常重要的任务之一。

1. 内存管理优化Java语言最大的优势是安全、简单易用、跨平台等特点,但最严重的弱点是内存泄漏。

因为Java语言是基于垃圾收集器的运行机制,例如在程序中使用的对象被引用之后并且没有被释放,JVM会一直保留这种引用,因此在程序运行的过程中就会产生内存泄漏。

为了提高程序的内存利用率,需要对内存管理进行优化:- 合理设置堆内存大小Java中的堆内存是所有对象和类的存储空间,通过-Xmx和-Xms设置堆内存大小,来平衡程序的性能与内存占用,尽可能地避免full GC和OOM,推荐使用-Xms和-Xmx参数为同一值。

- 垃圾收集器的选择JVM的垃圾收集器是指定在运行Java程序时管理Java对象的内存分配和释放策略的工具。

目前,Oracle提供了七种垃圾收集器。

为了达到最佳性能,需要根据应用程序的特点选择合适的垃圾收集器。

- 定期执行GC保证2s内执行一次gc,这种周期时间既不会太长,也不能太短。

因为如果gc时间过长,会影响程序正常运行;而如果gc过于频繁,会导致程序的吞吐量下降。

2. 线程优化Java虚拟机已经在JDK1.5版本时引入了ThreadLocal,它是一种非常好的Java语言中的线程优化技巧。

如果使用得当,ThreadLocal可以帮助程序减少同步操作,避免线程池的枷锁等问题。

以下为ThreadLocal的使用方式:// 定义一个全局的ThreadLocal变量private static ThreadLocal<SimpleDateFormat> threadLocal = new ThreadLocal<SimpleDateFormat>(){// 覆盖初始化方法@Overrideprotected SimpleDateFormat initialValue(){return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); }};// 主线程中设置默认时间格式public static void main(String args[]){System.out.println(threadLocal.get().format(new Date()));}// 其他线程中设置时间格式new Thread(new Runnable(){@Overridepublic void run(){threadLocal.set(new SimpleDateFormat());System.out.println(threadLocal.get().format(new Date()));}}).start();ThreadLocal是基于JVM的,它的使用不需要进行任何锁操作或者同步措施,这样就可以避免很多线程同步操作所带来的额外的系统开销。

Java性能优化的五种方式

Java性能优化的五种⽅式Java性能优化的五种⽅式⼀,JAVA性能优化之设计优化设计优化处于性能优化⼿段的上层。

它往往须要在软件开发之前进⾏。

在软件开发之前,系统架构师应该就评估系统可能存在的各种潜在问题和技术难点,并给出合理的设计⽅案,因为软件设计和系统架构对软件总体设计质量有决定性的影响。

所以,设计调优对系统的性能影响也是最⼤的,假设说,代码优化。

JVM优化都是对系统微观层次的“量”的优化,那设计优化就是对系统”质”的优化.设计优化的⼀⼤显著特征是:它能够规避某⼀个组件的性能问题,⽽是改良组件的实现;⽐⽅:组件A通过循环监控不断的检測时间E是否发⽣,其检測⾏为必定会占⽤部分系统资源,因此,开发者必须检測频率和资源消耗上取得平衡,假设检測频率太低,尽管降低了资源消耗,可是系统实时反应性就会降低,假设进⾏代码层的调优,就须要优化检測⽅法的实现及要求得⼀个最为恰当的检測频率.对于这个问题我们就能够⽤设计模式中的观察者模式 ,当事件E发⽣的时刻,由事件E通知组件A,从⽽触发组件A的⾏为.这样的设计从根本上攻克了存在性能隐患的循环监控,从根本上攻克了这⼀问题.进⾏设计优化时,设计⼈员和必须熟悉经常使⽤的设计⽅法,设计模式,以及主要的性能组件和经常使⽤的优化思想,并将其有机地集成在软件系统中.注意:⼀个良好的系统设计能够规避⾮常多潜在在的性能问题.因此,尽可能多花些时间在系统设计上,是创建⾼性能程序的关键⼆,JAVA性能优化之代码优化代码调优是在软件开发中,或者是软件开发完毕后,软件维护过程中进⾏的程序代码的改进和优化.代码优化涉及诸多编码技巧,须要开发者熟悉相关的语⾔API ,并在适合的场景中正确的使⽤相关API或类库.同⼀时候,对算法,数据结构的灵活使⽤,也是代码优化的⼀个重要内容.尽管代码优化时从微观上对性能进⾏调整,可是⼀个”好”的实现和⼀个”坏”的实现对系统的影响也是⾮常⼤的.⽐⽅,相同作为List的实现,LinkedList和ArrayList在随机訪问上的性能却差了好⼏个量级;⽐⽅相同是⽂件读写的实现,使⽤Stream⽅式和使⽤JAVA NIO的⽅式,其系能可能⼜会是还有⼀个数量级.因此,尽管与设计优化相⽐,笔者将代码优化成为在微观层⾯上的优化,但它却是对系统性能产⽣最直接影响的优化⽅法.三,JVM优化因为JAVA软件总是执⾏在JVM虚拟机之上。

Java性能调优与优化指南

Java性能调优与优化指南第一章:性能分析与监控在进行Java性能调优之前,首先需要对应用程序的性能进行全面分析和监控。

性能分析可以帮助我们确定应用程序中的瓶颈和性能瓶颈。

常用的性能分析工具包括Java虚拟机自带的JConsole 和VisualVM,以及第三方工具如YourKit和JProfiler。

通过这些工具,我们可以获取应用程序的CPU使用率、内存使用情况、线程数量以及函数的调用次数等信息,从而帮助我们定位性能瓶颈所在。

第二章:内存调优Java应用程序的内存管理是影响性能的一个重要因素。

在进行内存调优时,可以通过调整Java虚拟机的堆内存大小和使用的垃圾收集器来优化内存的使用效率。

一般来说,将堆内存设置为适当的大小可以避免频繁的垃圾回收,从而提高应用程序的性能。

此外,可以使用一些工具如Eclipse Memory Analyzer来分析应用程序的内存使用情况,并定位内存泄漏问题,有效地进行内存调优。

第三章:并发调优Java中的多线程编程是提高应用程序性能的重要手段之一。

在进行并发调优时,需要合理地设计和使用线程池,避免过多的线程竞争和阻塞。

可以通过使用Java中的锁机制和并发容器来提高线程的并发性能。

此外,合理地使用volatile和atomic关键字可以避免线程间的竞争条件,提高应用程序的性能。

通过合理地进行并发调优,可以有效地提升应用程序的吞吐量和响应速度。

第四章:IO调优在进行IO操作时,可以通过缓冲流来提高应用程序的IO性能。

使用缓冲流可以减少在内存和磁盘之间的频繁IO操作的次数,提高数据的读写效率。

此外,合理地使用NIO和异步IO机制可以进一步提升应用程序的IO性能。

通过调整缓冲区的大小和缓冲流的类型,可以根据应用场景的不同来进行IO调优,提高应用程序的性能。

第五章:数据库调优对于基于Java开发的应用程序来说,数据库的性能也是一个重要的考虑因素。

可以通过适当地调整数据库连接池的大小和使用合适的数据库连接池来提高数据库的访问速度。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

优化 Java 垃圾收集器改进系统性能

级别: 高级 李 晓华 (xiaohual@cn.ibm.com), IBM CDL ODSC部门工程师 2006 年 11 月 30 日 在系统的性能测试过程中,当系统的处理能力有某种变化趋势时, 除了关于等待队列、执行线程,EJB 池以及数据库连接池和 Statement Cache 方面的调优外,还要考虑到 Java 垃圾收集器(Garbage Collection,本文简称 GC)对系统性能的影响。本文介绍了如何分析系统的处理能力和 GC 之间的关系,以及如何通过改进 JVM 的配置来优化 GC,以提高系统的性能。

项目背景

某个大型项目的 CPU100% 的压力性能测试, 用以检查在系统运行环境不正常的情况下,系统可以运行到何种程度。测试过程是:请求测试的模拟器向系统不断发出大量请求, 系统接受由模拟器发出的请求,然后将请求置于一个任务池中,如果当前有空闲的线程,则该线程会从任务池中取出一个任务进行处理,如果没有空闲的线程,则该任务一直会待在任务池中,直到有空闲的线程来处理它。因此,任务池的队列的长度从某种意义上可以代表整个系统的处理能力,任务池队列的长度用 Q 值来表示,如果 Q 值超出了一定限额,将会有流量控制的线程将超出限额的待处理任务丢弃,以保证系统的稳定性。 整个测试要求得到系统所在服务器的负载达到将近 100% 时,系统的吞吐量,相应时间以及在超负荷下业务请求成功率。 问题现象描述 在测试过程中,任务池中累积的任务数起伏很大,正常时累积的任务数很小,但是每隔一段时间会累积大量的任务。由于累积的任务数超出任务池流量控制所定义的限额,所以每隔一段时间,大量的待处理任务被清除。因此测试结束后得到的在超负荷下业务请求成功率也不是很理想。 应用服务器的物理部署 一台AIX服务器(4CPU,4GMemory)来部署本Web应用程序;Web应用程序部署在中间件应用服务器上;部署了一个节点(Node),只配置一个应用服务器实例(Instance),没有做 Cluster 部署。

分析 检测 WebSphere Application Server 上的 Web Container,EJB Container , ORB Service,数据库连接池等设置均合理,然后怀疑问题的现象是不是与系统 GC 有关。当前 Java Virtual Machine 的配置为:Initial Heap Size:256 , Maximum Heap Size:3072。 为了验证任务池中累积的任务数的大幅度变化和系统 GC 是否存在一定的关系,通过对任务池的累积任务数和系统 GC 进行采样, 将采样后的数据进行分析,用以得出二者的关系。采样时遵循 Nyquist 采样定例:采样频率要大于被采集对象的频率的 2 倍。 否则,采样点很可能每次位于被采集对象的波形的某个点上,从而不能正确反映被采集对象的变化规律。 采样 通过观察,发现任务池的任务数目(以下用 Q 值代替)的变化周期大概是 5 到 6 秒,因此根据 Nyquist 采样定例,采样的时间间隔不能超过 2-3 秒,所以按照每秒来采样。 测试时间是 3 分钟,采样 180 次,系统的当前负载率是 99%。采样图如下所示:

PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn 图一 任务池 Q 值的采样图 由于系流量控制要求的限额是 450 个任务,也就是任务池中最多能累积 450 个任务,当任务池中累积的任务数超过 450 时,多余的任务会被流量控制直接丢弃,从上图可以看出,系统的Q值在很多时刻都大于 450,因此多次被丢弃任务,从而导致了任务请求成功率不高。 系统 GC 的采样

1. 在 WebSphere Administrative Console 上, 点击进入 Servers, 然后 Application servers > server1 > Process Definition > Java Virtual Machine, 在 Configuration 面板上,选上 Verbose garbage collection 选项。

图二 WebSphere Application Server的JVM配置示图

PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn2. 进入 <%WebSphere Application Server 的安装目录 %>/profiles/<% 所在的
profiles%>/logs/ <% 所在的 Server%>, 可以看到 native_stderr.log 文件,将其清空 3. 在高负载的条件下,进行高压测试 3 分钟 4. 将 native_stderr.log 文件拷贝出来,用 GCCollector 工具进行分析,其中 native_stderr.log 文件上记录了系统 GC 的数据。 5. 安装 GCCollector 工具:下载完 GCCollector.zip 后,解压缩,将里面 Lib 里的 3 个文件jfreechart-1.0.0-rc1.jar,jcommon-1.0.0-rc1.jar 和 GCCollector.jar 拷贝至 JRE 的 lib 目录下,然后在命令行控制台上进入JRE的安装目录,而后运行:java -classpath

jfreechart-1.0.0-rc1.jar;jcommon-1.0.0-rc1.jar -jar GCCollector.jar。

接着可以看到 GCCollector 的用户界面,在它的 Parser 菜单中选择 JRE 的版本,而后在 File 菜单中选择并打开刚才拷出的 native_stderr.log 文件。 下图是在高负载情况下,系统在当前配置下的 GC 分析图。

图三 系统的 GC 分析图

PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn由图三可以看出,系统没有内存泄漏的现象,每次 GC 所花的时间为 220ms 左右,从 GCCollector 的 Spreadsheet 可以查到,GC 的时间周期为 5-6 s,每次具体 GC 发生的时间,每次 GC 所花的时间。

6. 同样遵循 Nyquist 采样定例,对 GC 进行采样,采样后的数据同任务池中 Q 值的采样数据进行比较和分析,得出两者之间存在着密切的关系。下图为任务池 Q 值和 GC 数据采样分析图,由图中可以看出,每次任务池的 Q 值大幅度增长时,系统刚好发生 GC。二者的时间和周期几乎可以完全匹配。因此可以初步下一个结论,由于系统的 GC,导致了系统在某些时刻不能有足够的能力来处理请求,因此任务池的 Q 值在这些时候会因为任务的大量累积而巨幅涨大,即而超出限额的任务被流控所清除,导致了在超负荷下任务请求成功率不是很理想。

图四 任务池 Q 值和 GC 数据采样分析图

PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn 解决方法 当前的 GC 发生的频率和每次所花的时间还算正常,但是如果每次 GC 所花的 CPU 时间能减少,就能空出系统更多的能力处理任务池里的任务,用以降低任务池中的任务数,使得 Q 值基本上位于任务池的限额以下,这样可以提高在超负荷下业务请求的总的成功率。 当前 Java Virtual Machine 的配置为:Initial Heap Size:256 , Maximum Heap Size:3072。相对而言, Maximum Heap Size 设的有点偏大。对于不同的应用程序,最优化堆大小的设置都有可能不同。堆设置变大,GC 的频率会降低,应用程序会运行更长的时间后,才会进行 GC,带来的就是每次 GC 也会花更长的时间。从而 GC 调用占用系统更长的时间,使系统没有足够的能力处理请求,使得此刻任务池中的任务累积很多,Q 值很大,形成很高的峰值,超过流量控制的限额,超过限额数的任务被流量控制给直接丢弃,从而导致总的成功率不高。 因此,必须降低堆大小,使得 GC 的频率增大,每次 GC 所花时间降低,从而降低 Q 的峰值,使之位于系统的流量控制的范围之内,从而提高业务请求的总的成功率。 当前的流量控制所允许的峰值是 450,因此我们需要通过试验来验证,堆大小降低到什么值时,Q 值的峰值将低于 450,以保证总的成功率。 同时在峰值低于 450 的条件下,什么样的堆大小设置可以让系统的性能最佳。因为如果堆设置过小,会使得对象可分配空间变小,从而会频繁的使用垃圾收集机制来释放内存空间,而每次垃圾收集,都会耗用一定的系统资源。所以,我们要通过试验和监控数据,设法使的我们所设置的堆大小能够使得我们的程序运行最优化。 通过多次试验,我们得出结论:当 Java Virtual Machine 的配置为:Initial Heap Size:512 , Maximum Heap Size:1024 时,该系统性能最佳。 从 WebSphere Administrative Console上,依次点击 Servers->Application Servers,然后选择需要的 server,接着点击 Process Definition->Java Virtual Machine,而后在那里设置 Initial Heap Size:512 和 Maximum Heap Size:1024。这时的配置对于该应用系统相对较为合理。这时再次分析 3 分钟内的 GC 的数据,从下图可以看出,GC 的周期缩短了,每 1-2 秒就会发生一次 GC,但是每次 GC 所花费的 CPU 时间降低了,平均 130ms 左右。

图五 改进 JVM 配置后的 GC 分析图

PDF 文件使用 "pdfFactory" 试用版本创建 www.fineprint.cn

相关文档
最新文档