Java性能调优11个实用技巧

1.在必要之前,先不要优化

这可能是最最重要的性能调优技巧之一。你应该遵循常见的最佳实践,并尝试有效地实现你的用例。但这并不意味着在证明它是必要之前,替换任何标准库或构建复杂的优化。

在大多数情况下,过早的优化占用了大量的时间,使得代码难以读取和维护。更糟糕的是,这些优化通常不会带来任何好处,因为你花费了大量时间来优化应用程序的非关键部分。

那么,你如何证明你需要优化某些东西呢?

首先,你需要确定应用程序代码的速度,例如,为所有API调用指定一个最大响应时间,或者指定在特定时间范围内导入的记录数量。完成之后,你可以度量应用程序的哪些部分太慢而需要改进。当这样做之后,那么请继续看第二个调优技巧。

2.使用分析器来找到真正的瓶颈

在你遵循第一条建议,并确定你的应用程序的某些部分的确需要改进之后,问自己从哪里开始?

你可以用两种方法来解决这个问题:

你可以看一下你的代码,从看起来可疑或者你觉得它可能会产生问题的部分开始。

或者使用分析器,获取代码中每个部分的行为和性能的详细信息。

至于为什么应该总是遵循第二种方法。

答案应该很明显,基于分析器的方法能让你更好地理解代码的性能含义,并允许你关注最关键的部分。如果你曾经使用过分析器,你将会惊讶于代码的哪些部分造成了性能问题。然而,很多时候,你的第一次猜想会把你引向错误的方向。

3.为整个应用程序创建性能测试套件

这是另一个帮助你避免许多意想不到问题的一般技巧,这些问题通常发生在性能改进部署到生产环境之后。你应该经常定义测试整个应用程序的性能测试套件,并在你完成性能改进之前和之后运行它。

这些额外的测试运行将帮助你识别更改的功能和性能方面的影响,并确保你不会发布一个弊大于利的更新。如果你的任务运行于应用程序的多个不同部分比如数据库或缓存,这一点尤其重要。

4.首先解决最大的瓶颈问题

在创建了测试套件并使用分析器对应用程序进行分析之后,你就有了一个需要提高性能的问题列表,这很好,但它仍然不能回答你应该从哪里开始的问题。你可以从那些可以快速搞定的开始,亦或者从最重要的问题开始。

当然前者很诱人,因为这很快就能出结果。有时,可能需要说服其他团队成员或你的管理层,性能分析是值得的。

但总的来说,我建议首先着手处理最重要的性能问题。这将为你提供最大的性能改进,而且你可能只需要修复这些问题中的几个就可以解决你的性能需求。

在了解通用性能调优技巧之后,让我们再来仔细看看一些特定于Java的调优技巧。

5.使用StringBuilder以编程方式连接字符串

在Java中有许多不同的连接字符串的选项。例如,可以使用一个简单的+或+=、老的StringBuffer或StringBuilder。

那么,你应该选择哪种方法呢?

答案取决于连接字符串的代码。如果你以编程方式向字符串中添加新内容,例如,在for循环中,你应该使用StringBuilder。它比StringBuffer更容易使用和提供更好的性能。但是请记住,StringBuilder与StringBuffer不同,它不是线程安全的,而且可能不适合所有用例。

你只需要实例化一个新的StringBuilder,并调用append方法在字符串中添加一个新的部分。当你添加了所有的部分后,可以调用toString()方法来检索连接字符串。

下面的代码片段展示了一个简单的示例。在每次迭代过程中,这个循环将i转换成一个字符串,并将其添加到StringBuilder sb的空间中,因此到最后,这段代码写入“this is test0123456789”到日志文件。

StringBuilder sb=new StringBuilder(“This is a test”);for(int i=0;i<10;i++){sb.append(i);sb.append(”“);}log.info(sb.toString());

正如在代码片段中看到的,你可以为构造函数方法提供字符串的第一个元素。这将创建一个新的StringBuilder,其中包含提供的字符串和16个额外字符的容量。当你向StringBuilder中添加更多字符时,JVM将动态地改变StringBuilder的大小。

如果你已经知道自己的字符串包含多少字符,那么你可以向不同的构造函数方法提供这个数字,以实例化一个具有被定义容量的StringBuilder。这进一步提高了它的效率,因为它不需要动态扩展它的容量。

6.在声明中使用+连接字符串

当你在Java中实现第一个应用程序时,可能有人告诉你不应该用+来连接字符串。如果在应用程序逻辑中连接字符串这是正确的。字符串是不可变的,每个字符串连接的结果存储在一个新的字符串对象中。这需要额外的内存,并降低应用程序的速度,特别是在循环中连接多个字符串时。

在这些情况下,你应该遵循tip 5并使用StringBuilder。

但如果你只是将一个字符串分解成多行来提高代码的可读性,那就不是这样了。

Query q=em.createQuery(“SELECT a.id,a.firstName,a.lastName”+“FROM Author a”+“WHERE a.id=:id”);

在这些情况下,你应该用一个简单的+来连接你的字符串。Java编译器将优化它并在编译时执行连接。因此,在运行时,代码只使用1个字符,不需要连接。

7.尽可能使用基本数据类型

另一种避免开销,提高应用程序性能的快速方法就是使用原始数据类型而不是它们的包装类。因此,最好是使用int而不是Integer,或者是double而不是Double。这将让JVM将值存储在堆栈中,以减少内存消耗,并更有效地处理它。

8.尽量避免BigInteger和BigDecimal

由于我们已经讨论了数据类型,我们再来看下BigInteger和BigDecimal。尤其是后者,由于其精度高而受欢迎。但这是有代价的。

BigInteger和BigDecimal比简单的long或double需要更多的内存,并且大大降低所有的计算速度。因此,如果你需要额外的精度,或者你的数字超过了一个long范围,最好三思而后行。这可能是你在提升性能问题中唯一需要更改的地方,特别是当你正在实现一个数学算法。

9.首先检查当前日志级别

这个建议是显而易见的,但不幸的是,你会发现许多代码忽略它。在创建调试消息之前,应该先检查当前日志级别。

这里有两个例子来说明你不应该这样做。

//don’t do thislog.debug(“User[”+userName+“]called method X with[”+i+“]”);//or thislog.debug(String.format(“User[%s]called method X with[%d]”,userName,i));

在这两种情况下,你将执行所有需要的步骤来创建日志消息,而不知道日志框架是否使用日志消息。在创建调试消息之前,最好先检查当前日志级别。

//do thisif(log.isDebugEnabled()){log.debug(“User[”+userName+“]called method X with[”+i+“]”);}

10.使用Apache Commons StringUtils.Replace代替String.replace

一般来说,String.replace方法工作得很好,而且非常高效,特别是如果你使用的是Java 9。但是,如果应用程序需要大量的替换操作,并且你还没有更新到最新的Java版本,那么检查更快和更有效的替代方案仍然是有意义的。

一个候选就是Apache Commons Lang’s StringUtils.replace(https://commons.apache.org/proper/commons-lang/)方法。正如Lukas Eder在他最近的一篇博客文章(https://blog.jooq.org/2017/10/11/benchmarking-jdk-string-replace-vs-apache-commons-stringutils-replace/)中所描述的那样,它大大超过了Java 8的String.replace方法。

它只需要很小的改变。你只需要为Apache’s Commons Lang项目增加一个Maven依赖项到你的应用pom.xml,并用StringUtils.replace方法替换所有String.replace方法的调用。

//replace thistest.replace(“test”,“simple test”);//with thisStringUtils.replace(test,“test”,“simple test”);

11.缓存昂贵的资源,比如数据库连接

缓存是一种流行的解决方案来避免重复执行昂贵或频繁使用的代码片段。一般的想法很简单:重复使用这些资源比一次又一次地创建一个新的资源要便宜得多。

一个典型的例子就是在池中缓存数据库连接。创建新连接需要时间,如果重用现有连接,则可以避免。

还可以在Java语言本身中找到其他示例。例如,Integer类的valueOf方法缓存了-128和127之间的值。你可能会说,创建一个新整数并不太贵,但它经常使用,缓存最常用的值提供了性能方面的好处。

但当你考虑缓存时,请记住,缓存实现也会产生开销。你需要花费额外的内存来存储可重用资源,因此可能需要管理你的缓存,以使资源能够访问或删除过时的资源。

因此,在你开始缓存任何资源之前,请确保是经常使用。

原文地址:https://www.cnblogs.com/xuyiding/p/11621903.html

时间: 2024-09-29 06:52:36

Java性能调优11个实用技巧的相关文章

Java性能调优笔记

Java性能调优笔记 调优步骤:衡量系统现状.设定调优目标.寻找性能瓶颈.性能调优.衡量是否到达目标(如果未到达目标,需重新寻找性能瓶颈).性能调优结束. 寻找性能瓶颈 性能瓶颈的表象:资源消耗过多.外部处理系统的性能不足.资源消耗不多但程序的响应速度却仍达不到要求. 资源消耗:CPU.文件IO.网络IO.内存. 外部处理系统的性能不足:所调用的其他系统提供的功能或数据库操作的响应速度不够. 资源消耗不多但程序的响应速度却仍达不到要求:程序代码运行效率不够高.未充分使用资源.程序结构不合理. C

JAVA性能调优-在循环条件中不要使用表达式

1.JAVA性能调优-在循环条件中不要使用表达式 我们在学习JAVA性能调优的时候,经常能看到这一的一段话:在不做编译优化的情况下,在循环中,循环条件会被反复计算,如果不使用复杂表达式,而使循环条件值不变的话,程序将会运行的更快. import java.util.vector; class cel { void method(vector vector) { for (int i= 0; i < vector.size (); i++)  //violation ; //... } } 更正:

Java性能调优_深入Java程序性能调优(并行开发、JVM调优)

深入Java程序性能调优(阿姆达尔定律.缓存组件.并行开发.线程池.JVM调优)课程讲师:special课程分类:Java核心适合人群:初级课时数量:33课时更新程度:完成用到技术:阿姆达尔定律.缓存组件.并行开发.线程池.JVM调优涉及项目:模式在实际开发中运用深入Java程序性能调优下载: http://pan.baidu.com/s/1ntn0ZTB 密码: ijluJava性能调优:国内关于Java性能调优的课程非常少,如此全面深入介绍Java性能调优,北风算是独家,Special讲师,

推荐书籍:《Java性能调优指南》

本书作者是Java性能和Java HotSpot 虚拟机领域的佼佼者,帮助你利用现代软工实践提高性实战生涯中总结能,避免常见错误,从技巧和窍门. 利用G1克服并行.串行和CMS垃圾收集器的局限性了解G1  GC收集的各个阶段,包括年轻代和老年代在G1的引擎下微调您的应用程序确定潜在优化方案,解释实验结果,并付诸行动探索的HotSpot虚拟机内部使用热点VM服务代理分析.分流,并解决不同的热点 <Java性能调优指南>主要展示了如何在当今先进的多核硬件和复杂的操作系统环境下,系统且主动地提高Ja

java 性能调优工具

1.jstack 用法jstack [option] pid -l long listings,会打印出额外的锁信息,在发生死锁时可以用jstack -l pid来观察锁持有情况 -m mixed mode,不仅会输出Java堆栈信息,还会输出C/C++堆栈信息(比如Native方法) 找出进程内最耗费CPU的线程,可以使用ps -Lfp pid或者ps -mp pid -o THREAD, tid, time或者top -Hp pid printf "%x\n" pid 得到pid的

java 性能调优和GC

JAVA 性能调优和GC http://blog.csdn.net/gzh0222/article/details/7663181 JAVA GC调优手记 http://blog.csdn.net/firecoder/article/details/7225654 JAVA GC 日志详解 http://blog.csdn.net/alivetime/article/details/6895537 JAVA 内存参数设置 http://heipark.iteye.com/blog/1356113

JAVA性能调优- try/catch块和循环

1.JAVA性能调优-将try/catch块移出循环 据说把try/catch块放入循环体内,会极大的影响性能.因为使用了try/catch模块的使用,会让JAVA虚拟机做很多额外的工作.就好比对每个人说,"嗨,哥们,路上可能有蛇.于是听到的人只好手拿木棍,小心翼翼的往前走". 把try/catch块放到循环外面,就好比对一大群人说,"嗨,兄弟们,路上可能有蛇.于是听到的人安排部分人员拿木棍往前走,其他人基本不受影响" 这个理论蛮不错的,测试下对性能的实际影响 2.

java性能调优——技客时间

一.java性能调优的标准 cpu:有的应用需要大量计算,他们会长时间.不间断地占用 CPU 资源,导致其他资源无法争夺到 CPU 而响应缓慢,从而带来系统性能问题.例如,代码递归导致的无限循环,正则表达式引起的回溯,JVM 频繁的 FULL GC,以及多线程编程造成的大量上下文切换等,这些都有可能导致 CPU 资源繁忙. 内存:Java 程序一般通过 JVM 对内存进行分配管理,主要是用 JVM 中的堆内存来存储 Java 创建的对象.系统堆内存的读写速度非常快,所以基本不存在读写性能瓶颈.但

11 个简单的 Java 性能调优技巧

大多数开发人员理所当然地以为性能优化很复杂,需要大量的经验和知识.好吧,不能说这是完全错误的.优化应用程序以获得最佳性能不是一件容易的事情.但是,这并不意味着如果你不具备这些知识,就不能做任何事情.这里有11个易于遵循的建议和最佳实践可以帮助你创建一个性能良好的应用程序. 大部分建议是针对Java的.但也有若干建议是与语言无关的,可以应用于所有应用程序和编程语言.在讨论专门针对Java的性能调优技巧之前,让我们先来看看通用技巧. 1.在你知道必要之前不要优化 这可能是最重要的性能调整技巧之一.你