java优化策略相关.docx

上传人:b****8 文档编号:8942691 上传时间:2023-05-16 格式:DOCX 页数:20 大小:49.72KB
下载 相关 举报
java优化策略相关.docx_第1页
第1页 / 共20页
java优化策略相关.docx_第2页
第2页 / 共20页
java优化策略相关.docx_第3页
第3页 / 共20页
java优化策略相关.docx_第4页
第4页 / 共20页
java优化策略相关.docx_第5页
第5页 / 共20页
java优化策略相关.docx_第6页
第6页 / 共20页
java优化策略相关.docx_第7页
第7页 / 共20页
java优化策略相关.docx_第8页
第8页 / 共20页
java优化策略相关.docx_第9页
第9页 / 共20页
java优化策略相关.docx_第10页
第10页 / 共20页
java优化策略相关.docx_第11页
第11页 / 共20页
java优化策略相关.docx_第12页
第12页 / 共20页
java优化策略相关.docx_第13页
第13页 / 共20页
java优化策略相关.docx_第14页
第14页 / 共20页
java优化策略相关.docx_第15页
第15页 / 共20页
java优化策略相关.docx_第16页
第16页 / 共20页
java优化策略相关.docx_第17页
第17页 / 共20页
java优化策略相关.docx_第18页
第18页 / 共20页
java优化策略相关.docx_第19页
第19页 / 共20页
java优化策略相关.docx_第20页
第20页 / 共20页
亲,该文档总共20页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

java优化策略相关.docx

《java优化策略相关.docx》由会员分享,可在线阅读,更多相关《java优化策略相关.docx(20页珍藏版)》请在冰点文库上搜索。

java优化策略相关.docx

java优化策略相关

Java在九十年代中期出现以后,在赢得赞叹的同时,也引来了一些批评。

赢得的赞叹主要是Java的跨平台的操作性,即所谓的”WriteOnce,RunAnywhere”.但由于Java的性能和运行效率同C相比,仍然有很大的差距,从而引来了很多的批评。

   对于服务器端的应用程序,由于不大涉及到界面设计和程序的频繁重启,Java的性能问题看似不大明显,从而一些Java的技术,如JSP,Servlet,EJB等在服务器端编程方面得到了很大的应用,但实际上,Java的性能问题在服务器端依然存在。

下面我将分四个方面来讨论Java的性能和执行效率以及提高Java性能的一些方法。

   一.关于性能的基本知识

   1.性能的定义

   在我们讨论怎样提高Java的性能之前,我们需要明白“性能“的真正含义。

我们一般定义如下五个方面作为评判性能的标准。

   1)运算的性能----哪一个算法的执行性能最好

   2)内存的分配----程序需要分配多少内存,运行时的效率和性能最高。

   3)启动的时间----程序启动需要多少时间。

   4)程序的可伸缩性-----程序在用户负载过重的情况下的表现。

   5)性能的认识------用户怎样才能认识到程序的性能。

   对于不同的应用程序,对性能的要求也不同。

例如,大部分的应用程序在启动时需要较长的时间,从而对启动时间的要求有所降低;服务器端的应用程序通常都分配有较大的内存空间,所以对内存的要求也有所降低。

但是,这并不是所这两方面的性能可以被忽略。

其次,算法的性能对于那些把商务逻辑运用到事务性操作的应用程序来讲非常重要。

总的来讲,对应用程序的要求将决定对各个性能的优先级。

   2.怎样才能提高JAVA的性能

   提高JAVA的性能,一般考虑如下的四个主要方面:

   

(1)程序设计的方法和模式

   一个良好的设计能提高程序的性能,这一点不仅适用于JAVA,也适用也任何的编程语言。

因为它充分利用了各种资源,如内存,CPU,高速缓存,对象缓冲池及多线程,从而设计出高性能和可伸缩性强的系统。

   当然,为了提高程序的性能而改变原来的设计是比较困难的,但是,程序性能的重要性常常要高于设计上带来的变化。

因此,在编程开始之前就应该有一个好的设计模型和方法。

   

(2)JAVA布署的环境。

   JAVA布署的环境就是指用来解释和执行JAVA字节码的技术,一般有如下五种。

即解释指令技术(InterpreterTechnology),及时编译的技术(JustInTimeCompilierTechnology),适应性优化技术(AdaptiveOptimizationTechnology),动态优化,提前编译为机器码的技术(DynamicOptimization,AheadOfTimeTechnology)和编译为机器码的技术(TranslatorTechnology).

   这些技术一般都通过优化线程模型,调整堆和栈的大小来优化JAVA的性能。

在考虑提高JAVA的性能时,首先要找到影响JAVA性能的瓶颈(BottleNecks),在确认了设计的合理性后,应该调整JAVA布署的环境,通过改变一些参数来提高JAVA应用程序的性能。

具体内容见第二节。

   (3)JAVA应用程序的实现

   当讨论应用程序的性能问题时,大多数的程序员都会考虑程序的代码,这当然是对的,当更重要的是要找到影响程序性能的瓶颈代码。

为了找到这些瓶颈代码,我们一般会使用一些辅助的工具,如Jprobe,Optimizit,Vtune以及一些分析的工具如TowerJPerformance等。

这些辅助的工具能跟踪应用程序中执行每个函数或方法所消耗掉的时间,从而改善程序的性能。

   (4)硬件和操作系统

   为了提高JAVA应用程序的性能,而采用跟快的CPU和更多的内存,并认为这是提高程序性能的唯一方法,但事实并非如此。

实践经验和事实证明,只有遭到了应用程序性能的瓶颈,从而采取适当得方法,如设计模式,布署的环境,操作系统的调整,才是最有效的。

   3.程序中通常的性能瓶颈。

   所有的应用程序都存在性能瓶颈,为了提高应用程序的性能,就要尽可能的减少程序的瓶颈。

以下是在JAVA程序中经常存在的性能瓶颈。

    

   了解了这些瓶颈后,就可以有针对性的减少这些瓶颈,从而提高JAVA应用程序的性能

4.提高JAVA程序性能的步骤

   为了提高JAVA程序的性能,需要遵循如下的六个步骤。

   a)明确对性能的具体要求

   在实施一个项目之前,必须要明确该项目对于程序性能的具体要求,如:

这个应用程序要支持5000个并发的用户,并且响应时间要在5秒钟之内。

但同时也要明白对于性能的要求不应该同对程序的其他要求冲突。

   b)了解当前程序的性能

   你应该了解你的应用程序的性能同项目所要求性能之间的差距。

通常的指标是单位时间内的处理数和响应时间,有时还会比较CPU和内存的利用率。

   c)找到程序的性能瓶颈

   为了发现程序中的性能瓶颈,通常会使用一些分析工具,如:

TowerJApplicationPerformanceAnalyzer或VTune来察看和分析程序堆栈中各个元素的消耗时间,从而正确的找到并改正引起性能降低的瓶颈代码,从而提高程序的性能。

这些工具还能发现诸如过多的异常处理,垃圾回收等潜在的问题。

   d)采取适当的措施来提高性能

   找到了引起程序性能降低的瓶颈代码后,我们就可以用前面介绍过的提高性能的四个方面,即设计模式,JAVA代码的实现,布署JAVA的环境和操作系统来提高应用程序的性能。

具体内容将在下面的内容中作详细说明。

   e)只进行某一方面的修改来提高性能

   一次只改变可能引起性能降低的某一方面,然后观察程序的性能是否有所提高,而不应该一次改变多个方面,因为这样你将不知道到底哪个方面的改变提高了程序的性能,哪个方面没有,即不能知道程序瓶颈在哪。

   f)返回到步骤c,继续作类似的工作,一直达到要求的性能为止。

   二.JAVA布署的环境和编译技术

  开发JAVA应用程序时,首先把JAVA的源程序编译为与平台无关的字节码。

这些字节码就可以被各种基于JVM的技术所执行。

这些技术主要分为两个大类。

即基于解释的技术和基于提前编译为本地码的技术。

其示意图如下:

    

 

   具体可分为如下的五类:

  

   a)解释指令技术

   其结构图和执行过程如下:

    

 

   JAVA的编译器首先把JAVA源文件编译为字节码。

这些字节码对于JAVA虚拟机(JVM)来讲就是机器的指令码。

然后,JAVA的解释器不断的循环取出字节码进行解释并执行。

  这样做的优点是可以实现JAVA语言的跨平台,同时生成的字节码也比较紧凑。

JAVA的一些优点,如安全性,动态性都得保持;但缺点是省生成的字节码没有经过什么优化,同全部编译好的本地码相比,速度比较慢。

b)及时编译技术(JustInTime)

  及时编译技术是为了解决指令解释技术效率比较低,速度比较慢的情况下提出的,其结构图如下所示。

    

 

   其主要变化是在JAVA程序执行之前,又JIT编译器把JAVA的字节码编译为机器码。

从而在程序运行时直接执行机器码,而不用对字节码进行解释。

同时对代码也进行了部分的优化。

   这样做的优点是大大提高了JAVA程序的性能。

同时,由于编译的结果并不在程序运行间保存,因此也节约了存储空间了加载程序的时间;缺点是由于JIT编译器对所有的代码都想优化,因此也浪费了很多的时间。

   IBM和SUN公司都提供了相关的JIT产品。

   c)适应性优化技术(AdaptiveOptimizationTechnology)

   同JIT技术相比,适应性优化技术并不对所有的字节码进行优化。

它会跟踪程序运行的成个过程,从而发现需要优化的代码,对代码进行动态的优化。

对优化的代码,采取80/20的策略。

从理论上讲,程序运行的时间越长,代码就越优化。

其结构图如下:

    

 

   其优点是适应性优化技术充分利用了程序执行时的信息,发行程序的性能瓶颈,从而提高程序的性能;其缺点是在进行优化时可能会选择不当,发而降低了程序的性能。

   其主要产品又IBM,SUN的HotSpot.

   d)动态优化,提前编译为机器码的技术(DynamicOptimization,AheadOfTime)

   动态优化技术充分利用了JAVA源码编译,字节码编译,动态编译和静态编译的技术。

其输入时JAVA的原码或字节码,而输出是经过高度优化的可执行代码和个来动态库的混合(Window中是DLL文件,UNIX中是共享库.a.so文件)。

其结构如下:

    

 

   其优点是能大大提高程序的性能;缺点是破坏了JAVA的可移植性,也对JAVA的安全带来了一定的隐患。

   

   其主要产品是TowerJ3.0

三.优化JAVA程序设计和编码,提高JAVA程序性能的一些方法。

   通过使用一些前面介绍过的辅助性工具来找到程序中的瓶颈,然后就可以对瓶颈部分的代码进行优化。

一般有两种方案:

即优化代码或更改设计方法。

我们一般会选择后者,因为不去调用以下代码要比调用一些优化的代码更能提高程序的性能。

而一个设计良好的程序能够精简代码,从而提高性能。

   下面将提供一些在JAVA程序的设计和编码中,为了能够提高JAVA程序的性能,而经常采用的一些方法和技巧。

   1.对象的生成和大小的调整。

   JAVA程序设计中一个普遍的问题就是没有好好的利用JAVA语言本身提供的函数,从而常常会生成大量的对象(或实例)。

由于系统不仅要花时间生成对象,以后可能还需花时间对这些对象进行垃圾回收和处理。

因此,生成过多的对象将会给程序的性能带来很大的影响。

   例1:

关于String,StringBuffer,+和append

   JAVA语言提供了对于String类型变量的操作。

但如果使用不当,会给程序的性能带来影响。

如下面的语句:

   Stringname=newString(“HuangWeiFeng”);

   System.out.println(name+”ismyname”);

   看似已经很精简了,其实并非如此。

为了生成二进制的代码,要进行如下的步骤和操作。

   

(1)生成新的字符串newString(STR_1);

   

(2)复制该字符串。

   (3)加载字符串常量”HuangWeiFeng”(STR_2);

   (4)调用字符串的构架器(Constructor);

   (5)保存该字符串到数组中(从位置0开始)

   (6)从java.io.PrintStream类中得到静态的out变量

   (7)生成新的字符串缓冲变量newStringBuffer(STR_BUF_1);

   (8)复制该字符串缓冲变量

   (9)调用字符串缓冲的构架器(Constructor);

   (10)保存该字符串缓冲到数组中(从位置1开始)

   (11)以STR_1为参数,调用字符串缓冲(StringBuffer)类中的append方法。

   (12)加载字符串常量”ismyname”(STR_3);

   (13)以STR_3为参数,调用字符串缓冲(StringBuffer)类中的append方法。

   (14)对于STR_BUF_1执行toString命令。

   (15)调用out变量中的println方法,输出结果。

   由此可以看出,这两行简单的代码,就生成了STR_1,STR_2,STR_3,STR_4和STR_BUF_1五个对象变量。

这些生成的类的实例一般都存放在堆中。

堆要对所有类的超类,类的实例进行初始化,同时还要调用类极其每个超类的构架器。

而这些操作都是非常消耗系统资源的。

因此,对对象的生成进行限制,是完全有必要的。

   经修改,上面的代码可以用如下的代码来替换。

   StringBuffername=newStringBuffer(“HuangWeiFeng”);

   System.out.println(name.append(“ismyname.”).toString());

   系统将进行如下的操作。

   

(1)生成新的字符串缓冲变量newStringBuffer(STR_BUF_1);

   

(2)复制该字符串缓冲变量

   (3)加载字符串常量”HuangWeiFeng”(STR_1);

   (4)调用字符串缓冲的构架器(Constructor);

   (5)保存该字符串缓冲到数组中(从位置1开始)

   (6)从java.io.PrintStream类中得到静态的out变量

   (7)加载STR_BUF_1;

   (8)加载字符串常量”ismyname”(STR_2);

   (9)以STR_2为参数,调用字符串缓冲(StringBuffer)实例中的append方法。

   (10)对于STR_BUF_1执行toString命令。

(STR_3)

   (11)调用out变量中的println方法,输出结果。

由此可以看出,经过改进后的代码只生成了四个对象变量:

STR_1,STR_2,STR_3和STR_BUF_1.你可能觉得少生成一个对象不会对程序的性能有很大的提高。

但下面的代码段2的执行速度将是代码段1的2倍。

因为代码段1生成了八个对象,而代码段2只生成了四个对象。

   代码段1:

Stringname=newStringBuffer(“HuangWeiFeng”);

name+=”ismy”;

name+=”name”;

   代码段2:

StringBuffername=newStringBuffer(“HuangWeiFeng”);

name.append(“ismy”);

name.append(“name.”).toString();

   因此,充分的利用JAVA提供的库函数来优化程序,对提高JAVA程序的性能时非常重要的.其注意点主要有如下几方面;

   

(1)尽可能的使用静态变量(StaticClassVariables)

   如果类中的变量不会随他的实例而变化,就可以定义为静态变量,从而使他所有的实例都共享这个变量。

   例:

publicclassfoo

{

SomeObjectso=newSomeObject();

}

   就可以定义为:

publicclassfoo

{

staticSomeObjectso=newSomeObject();

}

   

(2)不要对已生成的对象作过多的改变。

   对于一些类(如:

String类)来讲,宁愿在重新生成一个新的对象实例,而不应该修改已经生成的对象实例。

   例:

Stringname=”Huang”;

name=”Wei”;

name=”Feng”;

   上述代码生成了三个String类型的对象实例。

而前两个马上就需要系统进行垃圾回收处理。

如果要对字符串进行连接的操作,性能将得更差。

因为系统将不得为此生成更多得临时变量。

如上例1所示。

   (3)生成对象时,要分配给它合理的空间和大小

   JAVA中的很多类都有它的默认的空间分配大小。

对于StringBuffer类来讲,默认的分配空间大小是16个字符。

如果在程序中使用StringBuffer的空间大小不是16个字符,那么就必须进行正确的初始化。

   (4)避免生成不太使用或生命周期短的对象或变量。

   对于这种情况,因该定义一个对象缓冲池。

以为管理一个对象缓冲池的开销要比频繁的生成和回收对象的开销小的多。

   (5)只在对象作用范围内进行初始化。

   JAVA允许在代码的任何地方定义和初始化对象。

这样,就可以只在对象作用的范围内进行初始化。

从而节约系统的开销。

   例:

SomeObjectso=newSomeObject();

If(x==1)then

{

Foo=so.getXX();

}

   可以修改为:

if(x==1)then

{

SomeObjectso=newSomeObject();

Foo=so.getXX();

}

 2.异常(Exceptions)

   JAVA语言中提供了try/catch来发方便用户捕捉异常,进行异常的处理。

但是如果使用不当,也会给JAVA程序的性能带来影响。

因此,要注意以下两点。

   

(1)避免对应用程序的逻辑使用try/catch

   如果可以用if,while等逻辑语句来处理,那么就尽可能的不用try/catch语句

   

(2)重用异常

   在必须要进行异常的处理时,要尽可能的重用已经存在的异常对象。

以为在异常的处理中,生成一个异常对象要消耗掉大部分的时间。

   3.线程(Threading)

   一个高性能的应用程序中一般都会用到线程。

因为线程能充分利用系统的资源。

在其他线程因为等待硬盘或网络读写而时,程序能继续处理和运行。

但是对线程运用不当,也会影响程序的性能。

   例2:

正确使用Vector类

   Vector主要用来保存各种类型的对象(包括相同类型和不同类型的对象)。

但是在一些情况下使用会给程序带来性能上的影响。

这主要是由Vector类的两个特点所决定的。

第一,Vector提供了线程的安全保护功能。

即使Vector类中的许多方法同步。

但是如果你已经确认你的应用程序是单线程,这些方法的同步就完全不必要了。

第二,在Vector查找存储的各种对象时,常常要花很多的时间进行类型的匹配。

而当这些对象都是同一类型时,这些匹配就完全不必要了。

因此,有必要设计一个单线程的,保存特定类型对象的类或集合来替代Vector类.用来替换的程序如下(StringVector.java):

publicclassStringVector

{

privateString[]data;

privateintcount;

publicStringVector(){this(10);//defaultsizeis10}

publicStringVector(intinitialSize)

{

data=newString[initialSize];

}

publicvoidadd(Stringstr)

{

//ignorenullstrings

if(str==null){return;}

ensureCapacity(count+1);

data[count++]=str;

}

privatevoidensureCapacity(intminCapacity)

{

intoldCapacity=data.length;

if(minCapacity>oldCapacity)

{

StringoldData[]=data;

intnewCapacity=oldCapacity*2;

data=newString[newCapacity];

System.arraycopy(oldData,0,data,0,count);

}

}

publicvoidremove(Stringstr)

{

if(str==null){return//ignorenullstr}

for(inti=0;i

{

//checkforamatch

if(data[i].equals(str))

{

System.arraycopy(data,i+1,data,i,count-1);//copydata

//allowpreviouslyvalidarrayelementbegc'd

data[--count]=null;

return;

}

}

}

publicfinalStringgetStringAt(intindex){

if(index<0){returnnull;}

elseif(index>count)

{

returnnull;//indexis>#strings

}

else{returndata[index];//indexisgood}

}

/****************StringVector.java*****************/

因此,代码:

VectorStrings=newVector();

Strings.add(“One”);

Strings.add(“Two”);

StringSecond=(String)Strings.elementAt

(1);

   可以用如下的代码替换:

StringVectorStrings=newStringVector();

Strings.add(“One”);

Strings.add(“Two”);

StringSecond=Strings.getStringAt

(1);

   这样就可以通过优化线程来提高JAVA程序的性能。

用于测试的程序如下(TestCollection.java):

importjava.util.Vector;

publicclassTestCollection

{

publicstaticvoidmain(Stringargs[])

{

TestCollectioncollect=newTestCollection();

if(args.length==0)

{

System.out.println(

"Usage:

javaTestCollection[vector|stringvector]");

System.exit

(1);

}

if(args[0].equals("vector"))

{

Vectorstore=newVector();

longstart=System.currentTimeMillis();

for(inti=0;i<1000000;i++)

{

store.addElement("string");

}

longfinish=System.currentTimeMillis();

System.out.println((finish-start));

start=System.currentTimeMillis();

for(inti=0;i<1000000;i++)

{

Stringresult=(String)s

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 经管营销 > 经济市场

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2