
正文
java代码性能分析 java代码性能分析工具
提示:扫一扫查出行【扫一扫了解最新限行尾号】
复制提示
Java性能调优的使用技巧有哪些?
对于很多学习开发java代码性能分析的人员来说,进行性能优化是一个非常复杂的问题,并且还需要大量的经验和知识积累。想要优化达到一定的效果是一件非常不容易的事情,很多人认为需要在经验非常丰富的情况下才能使用,其实在没有获得丰富经验和知识之前也是可能进行性能优化的,北京电脑培训认为只要掌握一定的方法和技巧就能创建出性能良好的程序。
在进行性能调优的过程中,主要是基于Java语言,但是也有一些是可以使用在应用程序和编程语言中。那么在使用之前,北京IT培训为大家一起讨论通用的性能调优技巧。
1、先不要急着优化
在必要之前,一定不要急着进行优化,这是一种非常重要的性能调优方法。在进行调优过程中,我们应该遵守最佳的实践方法,这样才能得到有效的实现。但是在使用过程中并不意味着需要证明必要性,最好的方法是使用标准库或是构建复杂进行优化。
在很多情况下,如果过早的进行优化会占用很大一部分的时间,还会出现代码不好读取和维护的情况。如果更严重,这样的优化是不会带来任何好处的,很多时候你花费大量时间进行优化的程序并非是最关键的地方。
2、使用分析器找到瓶颈
在确定应用程序的某些部分需要优化的时候,应从哪里进行入手呢java代码性能分析?解决这种情况主要有两种方法,北京IT培训认为首先就是java代码性能分析了解代码,找出看上去存在问题和可能产生疑惑的地方开始优化。其次是可以使用分析器进行优化,分析器能够获取代码中每个部分的性能详细信息。
3、为应用程序创建测试套件
这个一种能够帮助你避免很多问题的方法,很多问题主要是发生在性能部署在生产环境之后。在使用过程中,你可以定义测试整个应用程序的套件,这样就能完成性能改造和运行。在测试运行的过程中,能够帮助你更改功能和性能的影响,这样才能让利大于弊。如果在使用过程中,你的任务运行于多个应用程序的多个部分,例如数据库、缓存等,这是非常重要的。
进行Java性能调优的技巧有很多种,在进行性能调优的过程中可以选择适合自己的方法,在提高应用程序的性能中,不需要做大量的工作。北京电脑培训认为最好的方法就是进行稍微努力,这样就能很好的应用到代码中。
相关问答
Q1: Java编程中的性能优化如何实现?
性能优化我觉得应该分两步走,第一步:寻找性能瓶颈,第二步:性能调优;
下面分别进行分析:
第一步:寻找性能瓶颈
通常性能瓶颈的表象是资源消耗过多、外部处理系统的性能不足;或者资源消耗不多,但是程序效应还是很慢;
资源主要消耗在cpu,文件io,网络io以及内存方面,当某一资源消耗过多会造成系统响应慢;
外部处理系统的性能不足主要是所调用其他系统提供的功能或数据库的响应速度不够,外部系统慢可能也是资源消耗过多导致,数据库响应慢可以对数据库进行调优;
资源消耗不多但仍然慢主要原因是程序代码运行效率不高,未充分使用资源或程序结构不合理;
1.1cpu消耗分析
可以通过相关命令比如top,pidstat,找出各个类型消耗cpu的占比,最常见的就是us和sy类型分别代表用户进程消耗和线程间切换消耗;如果us过高可以找到相关的线程ID然后分析代码;如果sy过高是不是启动了过多的线程导致线程切换过多;
1.2文件io消耗
要跟踪线程的文件IO消耗,可以通过pidstat来查找,可以查到每秒的读写kb数;找到读写kb数多个线程,然后结合jstack找到相关的java代码,然后分析;
1.3网络io消耗
可以通过sar来分析网络的消耗状况,但是不能具体到每个线程所消耗的网络IO,只能对线程dump,查找产生了大量网络io的线程;
1.4内存消耗
结合top或pidstat,以及jvm的内存分析工具来分析内存消耗;要区分是jvm外的物理内存还是jvmheap区内存;如果是jvm外的物理内存要分析程序中DirectByteBuffer,如果是jvmheap可以通过jvisualvm来分析;
1.5资源消耗不多但仍然慢
主要原因是:锁竞争激烈,未充分使用硬件资源,数据量增长
第二步:性能调优
2.1jvm调优
主要包括各个代的大小、GC策略等;代大小的设置:避免新生代大小设置过小,或者过大;避免Survivor区过小或过大;合理设置新生代存活周期;GC策略根据吞吐量优先还是延迟优先进行设置策略;
2.2程序调优
1.CPU消耗严重解决
us过高主要是执行线程无任何挂起动作,可以进行Thread.sleep操作;sy过高主要是因为创建了过多的线程导致线程上下文切换;
2.文件IO消耗严重解决
造成文件IO消耗严重的原因主要是多个线程写大量的数据到同一个文件,导致文件很快变的很大,从而写入速度越来越慢,并造成各线程激烈竞争争抢文件锁,常用的调优方法:异步写文件,批量读写,限流,限制文件大小;
3.网络IO消耗严重解决
主要原因是同时发送或者接受的包太多,解决办法就是限流;
4.内存消耗严重解决
解决:释放不必要的引用,使用对象缓存池,采用合理的缓存失效策略,合理使用softReference和WeakReference;
2.3资源消耗不多但仍然慢
主要原因是:锁竞争激烈,未充分使用硬件资源
Q2: 简单的Java性能调优技巧?
大多数JAVA开发人员理所当然地以为性能优化很复杂java代码性能分析,需要大量java代码性能分析的经验和知识。好吧,不能说这是完全错误的。
优化应用程序以获得最佳性能不是一件容易的事情。但是,这并不意味着如果你不具备这些知识,就不能做任何事情。这里有一些易于遵循的调优方式,霍营java培训建议可以做个参考!
大部分建议是针对Java的。但也有若干建议是与语言无关的,可以应用于所有应用程序和编程语言。在讨论专门针对Java的性能调优技巧之前,让我们先来看看通用技巧。
1.在你知道必要之前不要优化
这可能是最重要的性能调整技巧之一。你应该遵循常见的最佳实践做法并尝试高效地实现用例。但是,这并不意味着在你证明必要之前,你应该更换任何标准库或构建复杂的优化。
在大多数情况下,过早优化不但会占用大量时间,而且会使代码变得难以阅读和维护。更糟糕的是,这些优化通常不会带来任何好处,因为你花费大量时间来优化的是应用程序的非关键部分。
那么,你如何证明你需要优化一些东西呢?
首先,你需要定义应用程序代码的速度得多快,例如,为所有API调用指定最大响应时间,或者指定在特定时间范围内要导入的记录数量。在完成这些之后,你就可以测量应用程序的哪些部分太慢需要改进。然后,接着看第二个技巧。
2.使用分析器查找真正的瓶颈
在你遵循第一个建议并确定java代码性能分析了应用程序的某些部分需要改进后,那么从哪里开始呢?
你可以用两种方法来解决问题:
·查看你的代码,并从看起来可疑或者你觉得可能会产生问题的部分开始。
·或者使用分析器并获取有关代码每个部分的行为和性能的详细信息。
希望不需要我解释为什么应该始终遵循第二种方法的原因。
很明显,基于分析器的方法可以让你更好地理解代码的性能影响,并使你能够专注于最关键的部分。如果你曾使用过分析器,那么你一定记得曾经你是多么惊讶于一下就找到了代码的哪些部分产生了性能问题。老实说,我第一次的猜测不止一次地导致我走错了方向。
3.为整个应用程序创建性能测试套件
这是另一个通用技巧,可以帮助你避免在将性能改进部署到生产后经常会发生的许多意外问题。你应该总是定义一个测试整个应用程序的性能测试套件,并在性能改进之前和之后运行它。
这些额外的测试运行将帮助你识别更改的功能和性能副作用,并确保不会导致弊大于利的更新。如果你工作于被应用程序若干不同部分使用的组件,如数据库或缓存,那么这一点就尤其重要。
Q3: Java代码如何优化?从哪些方面入手?分析?
1)尽量指定类、方法java代码性能分析的final修饰符。带有final修饰符的类是不可派生的java代码性能分析,Java编译器会寻找机会内联所有的final方法,内联对于提升Java运行效率作用重大,此举能够使性能平均提高50%。
2)尽量重用对象。由于Java虚拟机不仅要花时间生成对象,以后可能还需要花时间对这些对象进行垃圾回收和处理,因此生成过多的对象将会给程序的性能带来很大的影响。
3)尽可能使用局部变量。调用方法时传递的参数以及在调用中创建的临时变量都保存在栈中速度较快,其java代码性能分析他变量,如静态变量、实例变量等,都在堆中创建速度较慢。
4)慎用异常。异常对性能不利,只要有异常被抛出,Java虚拟机就必须调整调用堆栈,因为在处理过程中创建了一个新的对象。异常只能用于错误处理,不应该用来控制程序流程。
5)乘法和除法使用移位操作。用移位操作可以极大地提高性能,因为在计算机底层,对位的操作是最方便、最快的,但是移位操作虽然快,可能会使代码不太好理解,因此最好加上相应的注释。
6)尽量使用HashMap、ArrayList、StringBuilder,除非线程安全需要,否则不推荐使用 Hashtable、Vector、StringBuffer,后三者由于使用同步机制而导致了性能开销。
尽量在合适的场合使用单例。使用单例可以减轻加载的负担、缩短加载的时间、提高加载的效率,但并不是所有地方都适用于单例。
Q4: Java程序的性能优化StringBuffer与Vector
Java使得复杂应用的开发变得相对简单 毫无疑问 它的这种易用性对Java的大范围流行功不可没 然而 这种易用性实际上是一把双刃剑 一个设计良好的Java程序 性能表现往往不如一个同样设计良好的C++程序 在Java程序中 性能问题的大部分原因并不在于Java语言 而是在于程序本身 养成好的代码编写习惯非常重要 比如正确地 巧妙地运用java lang String类和java util Vector类 它能够显著地提高程序的性能 下面我们就来具体地分析一下这方面的问题
在java中 使用最频繁 同时也是滥用最多的一个类或许就是java lang String 它也是导致代码性能低下最主要的原因之一 请考虑下面这个例子
String s = Testing String ;String s = Concatenation Performance ;String s = s + + s ;
几乎所有的Java程序员都知道上面的代码效率不高 那么 我们应该怎么办呢?也许可以试试下面这种代码
StringBuffer s = new StringBuffer();s append( Testing String );s append( );s append( Concatenation Performance );String s = s toString();
这些代码会比第一个代码片段效率更高吗?答案是否定的 这里的代码实际上正是编译器编译第一个代码片段之后的结果 既然与使用多个独立的String对象相比 StringBuffer并没有使代码有任何效率上的提高 那为什么有那么多Java书籍批评第一种方法 推荐使用第二种方法?
第二个代码片段用到了StringBuffer类(编译器在第一个片段中也将使用StringBuffer类) 我们来分析一下StringBuffer类的默认构造函数 下面是它的代码
public StringBuffer() { this( ); }
默认构造函数预设了 个字符的缓存容量 现在我们再来看看StringBuffer类的append()方法
public synchronized StringBuffer append(String str) {if (str == null) { str = String valueOf(str); } int len = str length(); int newcount = count + len; if (newcount value length) expandCapacity(newcount); str getChars( len value count); count = newcount; return this;}
append()方法首先计算字符串追加完成后的总长度 如果这个总长度大于StringBuffer的存储能力 append()方法调用私有的expandCapacity()方法 expandCapacity()方法在每次被调用时使StringBuffer存储能力加倍 并把现有的字符数组内容复制到新的存储空间
在第二个代码片段中(以及在第一个代码片段的编译结果中) 由于字符串追加操作的最后结果是 Testing String Concatenation Performance 它有 个字符 StringBuffer的存储能力必须扩展两次 从而导致了两次代价昂贵的复制操作 因此 我们至少有一点可以做得比编译器更好 这就是分配一个初始存储容量大于或者等于 个字符的StringBuffer 如下所示
StringBuffer s = new StringBuffer( );s append( Testing String );s append( );s append( Concatenation Performance );String s = s toString();
再考虑下面这个例子
String s = ;int sum = ;for(int I= ; I ; I++) { sum += I; s = s + + +I ; }s = s + = + sum;
分析一下为何前面的代码比下面的代码效率低
StringBuffer *** = new StringBuffer();int sum = ; for(int I= ; I ; I++){ sum + = I; *** append(I) append( + ); }String s = *** append( = ) append(sum) toString();
原因就在于每个s = s + + + I操作都要创建并拆除一个StringBuffer对象以及一个String 对象 这完全是一种浪费 而在第二个例子中我们避免了这种情况
我们再来看看另外一个常用的Java类——java util Vector 简单地说 一个Vector就是一个java lang Object实例的数组 Vector与数组相似 它的元素可以通过整数形式的索引访问 但是 Vector类型的对象在创建之后 对象的大小能够根据元素的增加或者删除而扩展 缩小 请考虑下面这个向Vector加入元素的例子
Object obj = new Object();Vector v = new Vector( );for(int I= ; I ; I++) { v add( obj); }
除非有绝对充足的理由要求每次都把新元素插入到Vector的前面 否则上面的代码对性能不利 在默认构造函数中 Vector的初始存储能力是 个元素 如果新元素加入时存储能力不足 则以后存储能力每次加倍 Vector类就象StringBuffer类一样 每次扩展存储能力时 所有现有的元素都要复制到新的存储空间之中 下面的代码片段要比前面的例子快几个数量级
Object obj = new Object();Vector v = new Vector( );for(int I= ; I ; I++) { v add(obj); }
同样的规则也适用于Vector类的remove()方法 由于Vector中各个元素之间不能含有 空隙 删除除最后一个元素之外的任意其他元素都导致被删除元素之后的元素向前移动 也就是说 从Vector删除最后一个元素要比删除第一个元素 开销 低好几倍
假设要从前面的Vector删除所有元素 我们可以使用这种代码
for(int I= ; I ; I++){ v remove( ); }
但是 与下面的代码相比 前面的代码要慢几个数量级
for(int I= ; I ; I++){ v remove(v size() ); }
从Vector类型的对象v删除所有元素的最好方法是
v removeAllElements();
假设Vector类型的对象v包含字符串 Hello 考虑下面的代码 它要从这个Vector中删除 Hello 字符串
String s = Hello ; int i = v indexOf(s); if(I != ) v remove(s);
这些代码看起来没什么错误 但它同样对性能不利 在这段代码中 indexOf()方法对v进行顺序搜索寻找字符串 Hello remove(s)方法也要进行同样的顺序搜索 改进之后的版本是
String s = Hello ; int i = v indexOf(s); if(I != ) v remove(i);
这个版本中我们直接在remove()方法中给出待删除元素的精确索引位置 从而避免了第二次搜索 一个更好的版本是
String s = Hello ; v remove(s);
最后 我们再来看一个有关Vector类的代码片段
for(int I= ; Iv size(); I+=){}如果v包含 个元素 这个代码片段将调用v size()方法 次 虽然size方法是一个简单的方法 但它仍旧需要一次方法调用的开销 至少JVM需要为它配置以及清除堆栈环境 在这里 for循环内部的代码不会以任何方式修改Vector类型对象v的大小 因此上面的代码最好改写成下面这种形式
int size = v size(); for(int I= ; Isize; I++){}
lishixinzhi/Article/program/Java/gj/201311/27752
关于java代码性能分析和java代码性能分析工具的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。







