十分简单易懂的Java应用程序性能调优技巧分享

大多数开发人员理所当然地以为性能优化很复杂,需要大量的经验和知识。好吧,不能说这是完全错误的。优化应用程序以获得最佳性能不是一件容易的事情。但是,这并不意味着如果你不具备这些知识,就不能做任何事情。这里有11个易于遵循的建议和最佳实践可以帮助你创建一个性能良好的应用程序。

大部分建议是针对Java的。但也有若干建议是与语言无关的,可以应用于所有应用程序和编程语言。在讨论专门针对Java的性能调优技巧之前,让我们先来看看通用技巧。

1.在你知道必要之前不要优化

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

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

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

首先,你需要定义应用程序代码的速度得多快,例如,为所有API调用指定最大响应时间,或者指定在特定时间范围内要导入的记录数量。在完成这些之后,你就可以测量应用程序的哪些部分太慢需要改进。然后,接着看第二个技巧。

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

在你遵循第一个建议并确定了应用程序的某些部分需要改进后,那么从哪里开始呢?

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

查看你的代码,并从看起来可疑或者你觉得可能会产生问题的部分开始。
或者使用分析器并获取有关代码每个部分的行为和性能的详细信息。
希望不需要我解释为什么应该始终遵循第二种方法的原因。

很明显,基于分析器的方法可以让你更好地理解代码的性能影响,并使你能够专注于最关键的部分。如果你曾使用过分析器,那么你一定记得曾经你是多么惊讶于一下就找到了代码的哪些部分产生了性能问题。老实说,我第一次的猜测不止一次地导致我走错了方向。

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

这是另一个通用技巧,可以帮助你避免在将性能改进部署到生产后经常会发生的许多意外问题。你应该总是定义一个测试整个应用程序的性能测试套件,并在性能改进之前和之后运行它。

这些额外的测试运行将帮助你识别更改的功能和性能副作用,并确保不会导致弊大于利的更新。如果你工作于被应用程序若干不同部分使用的组件,如数据库或缓存,那么这一点就尤其重要。

4.首先处理最大的瓶颈

在创建测试套件并使用分析器分析应用程序之后,你可以列出一系列需要解决以提高性能的问题。这很好,但它仍然不能回答你应该从哪里开始的问题。你可以专注于速效方案,或从最重要的问题开始。

速效方案一开始可能会很有吸引力,因为你可以很快显示第一个成果。但有时,可能需要你说服其他团队成员或管理层认为性能分析是值得的——因为暂时看不到效果。

但总的来说,我建议首先处理最重要的性能问题。这将为你提供最大的性能改进,而且可能再也不需要去解决其中一些为了满足性能需求的问题。

常见的性能调整技巧到此结束。下面让我们仔细看看一些特定于Java的技巧。

5.使用StringBuilder以编程方式连接String

有很多不同的选项来连接Java中的String。例如,你可以使用简单的+或+ =,以及StringBuffer或StringBuilder。

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

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

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

下面的代码片段显示了一个简单的例子。在每次迭代期间,这个循环将i转换为一个String,并将它与一个空格一起添加到StringBuilder sb中。所以,最后,这段代码将在日志文件中写入“This is a test0 1 2 3 4 5 6 7 8 9”。

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

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

如果你已经知道你的String将包含多少个字符,则可以将该数字提供给不同的构造方法以实例化具有定义容量的StringBuilder。这进一步提高了效率,因为它不需要动态扩展其容量。

6.使用+连接一个语句中的String

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

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

但是,如果你只是将字符串分成多行来改善代码的可读性,那情况就不一样了。

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

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

7.尽可能使用基元

避免任何开销并提高应用程序性能的另一个简便而快速的方法是使用基本类型而不是其包装类。所以,最好使用int来代替Integer,使用double来代替Double。这允许JVM将值存储在堆栈而不是堆中以减少内存消耗,并作出更有效的处理。

8.试着避免BigInteger和BigDecimal

既然我们在讨论数据类型,那么我们也快速浏览一下BigInteger和BigDecimal吧。尤其是后者因其精确性而受到大家的欢迎。但是这是有代价的。

BigInteger和BigDecimal比简单的long或double需要更多的内存,并且会显著减慢所有计算。所以,你如果需要额外的精度,或者数字将超过long的范围,那么最好三思而后行。这可能是你需要更改以解决性能问题的唯一方法,特别是在实现数学算法的时候。

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

这个建议应该是显而易见的,但不幸的是,很多程序员在写代码的时候都会大多会忽略它。在你创建调试消息之前,始终应该首先检查当前日志级别。否则,你可能会创建一个之后会被忽略的日志消息字符串。

这里有两个反面例子。

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

在上面两种情况中,你都将执行创建日志消息所有必需的步骤,在不知道日志框架是否将使用日志消息的前提下。因此在创建调试消息之前,最好先检查当前的日志级别。

// do this
if (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的StringUtils.replace方法。正如Lukas Eder在他最近的一篇博客文章中所描述的,StringUtils.replace方法远胜Java 8的String.replace方法。

而且它只需要很小的改动。即添加Apache Commons Lang项目的Maven依赖项到应用程序pom.xml中,并将String.replace方法的所有调用替换为StringUtils.replace方法。

// replace this
test.replace(“test”, “simple test”);
// with this
StringUtils.replace(test, “test”, “simple test”);

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

缓存是避免重复执行昂贵或常用代码片段的流行解决方案。总的思路很简单:重复使用这些资源比反复创建新的资源要便宜。

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

你还可以在Java语言本身找到其他例子。例如,Integer类的valueOf方法缓存了-128到127之间的值。你可能会说创建一个新的Integer并不是太昂贵,但是由于它经常被使用,以至于缓存最常用的值也可以提供性能优势。

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

所以,在开始缓存任何资源之前,请确保实施缓存是值得的,也就是说必须足够多地使用它们。

总结

正如你所看到的,有时不需要太多工作就可以提高应用程序的性能。本文中的大部分建议只需要你稍作努力就可以将它们应用于你的代码。

但是,最重要的还是那些与是什么编程语言无关的技巧:

在你知道必要之前不要优化
使用分析器查找真正的瓶颈
首先处理最大的瓶颈

以上就是本文关于十分简单易懂的Java性能调优技巧分享的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站:

Java实现微信公众平台朋友圈分享功能详细代码

java原生序列化和Kryo序列化性能实例对比分析

Java编程子类能否重写父类的静态方法探索

如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

(0)

相关推荐

  • Java性能调优概述

    程序性能的主要表现点: 执行速度:程序的反映是否迅速,响应时间是否足够短 内存分配:内存分配是否合理,是否过多地消耗内存或者存在内存泄漏 启动时间:程序从运行到可以正常处理业务需要花费多少时间 负载承受能力:当系统压力上升时,系统的执行速度.响应时间的上升曲线是否平缓 衡量程序性能的主要指标: 执行时间:程序从运行到结束所使用的时间 CPU时间:函数或者线程占用CPU的时间 内存分配:程序在运行时占用内容的空间 磁盘吞吐量:描述I/O的使用情况 网络吞吐量:描述网络的使用情况 响应时间:系统对用

  • 十分简单易懂的Java应用程序性能调优技巧分享

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

  • 分享Java性能调优的11个实用技巧

    大多数开发人员认为性能优化是个比较复杂的问题,需要大量的经验和知识.是的,这并不没有错.诚然,优化应用程序以获得最好的性能并不是一件容易的事情,但这并不意味着你在没有获得这些经验和知识之前就不能做任何事.下面有几个很容易遵循的建议和最佳实践能够帮你创建一个性能良好的应用程序. 这些建议中的大多数都是基于Java的,但是也不一定,也有一些是可以应用于所有的应用程序和编程语言的.在我们分享基于Java的性能调优技巧之前,让我们先讨论一下这些通用的性能调优技巧. 1.在必要之前,先不要优化 这可能是最

  • java性能调优System的gc垃圾回收方法

    目录 一.什么是System.gc()? 二.谁可以调用System.gc()? 三.调用System.gc()有什么弊端? 四.哪些场景适合显式调用System.gc()? 五.如何检测您的应用程序正在进行System.gc()? 六.如何禁止GC显式调用或调整调用GC的频率? 搜索和替换 通过JVM参数强制禁止 RMI 一.什么是System.gc()? System.gc()是用Java,C#和许多其他流行的高级编程语言提供的API.当它被调用时,它将尽最大努力从内存中清除垃圾(即未被引用

  • 10个MySQL性能调优的方法

    MYSQL 应该是最流行了 WEB 后端数据库.WEB 开发语言最近发展很快,PHP, Ruby, Python, Java 各有特点,虽然 NOSQL 最近越來越多的被提到,但是相信大部分架构师还是会选择 MYSQL 来做数据存储. MYSQL 如此方便和稳定,以至于我们在开发 WEB 程序的时候很少想到它.即使想到优化也是程序级别的,比如,不要写过于消耗资源的 SQL 语句.但是除此之外,在整个系统上仍然有很多可以优化的地方. 1. 选择合适的存储引擎: InnoDB 除非你的数据表使用来做

  • Android性能调优利器StrictMode应用分析

    作为Android开发,日常的开发工作中或多或少要接触到性能问题,比如我的Android程序运行缓慢卡顿,并且常常出现ANR对话框等等问题.既然有性能问题,就需要进行性能优化.正所谓工欲善其事,必先利其器.一个好的工具,可以帮助我们发现并定位问题,进而有的放矢进行解决.本文主要介绍StrictMode 在Android 应用开发中的应用和一些问题. 什么是StrictMode StrictMode意思为严格模式,是用来检测程序中违例情况的开发者工具.最常用的场景就是检测主线程中本地磁盘和网络读写

  • JVM性能调优实战:让你的IntelliJ Idea纵享丝滑

    本文已被Github仓库收录 https://github.com/silently9527/JavaCore 前言 在前面整理了一篇关于JVM故障诊断和处理工具,考虑到大部分的Java程序员都使用的是IntelliJ Idea,本篇就使用工具来实战演练对IntelliJ Idea运行速度调优 调优前的运行状态 原始配置内容 要查询idea原始配置文件的路径可以在VisualVM中的概述中查看 原始配置内容: -XX:ReservedCodeCacheSize=240m -XX:+UseComp

  • java虚拟机之JVM调优详解

    JVM常用命令行参数 1. 查看参数列表 虚拟机参数分为基本和扩展两类,在命令行中输入 JAVA_HOME\bin\java就可得到基本参数列表. 在命令行输入 JAVA_HOME\bin\java –X就可得到扩展参数列表. 2. 基本参数说明: -client,-server: 两种Java虚拟机启动方式,client模式启动比较快,但是性能和内存管理相对较差,server模式启动比较慢,但是运行性能比较高,windos上采用的是client模式,Linux采用server模式 -class

  • AngularJS进行性能调优的7个建议

    AnglarJS作为一款优秀的Web框架,可大大简化前端开发的负担.近日Sebastian Fröstl在一篇博文<AngularJS Performance Tuning for Long Lists>中表示AnglarJS在处理包含复杂数据结构的大型列表时,其运行速度会非常慢.他在文中同时分享了解决方案.下面为该文的译文. AnglarJS很棒,但当处理包含复杂数据结构的大型列表时,其运行速度就会非常慢.这是我们将核心管理页面迁移到AngularJS过程中遇到的问题.这些页面在显示500行

  • web性能优化之javascript性能调优

    JavaScript 是一个比较完善的前端开发语言,在现今的 web 开发中应用非常广泛,尤其是对 Web 2.0 的应用.随着 Web 2.0 越来越流行的今天,我们会发现:在我们的 web 应用项目中,会有大量的 JavaScript 代码,并且以后会越来越多.JavaScript 作为一个解释执行的语言,以及它的单线程机制,决定了性能问题是 JavaScript 的软肋,也是 web 软件工程师们在写 JavaScript 需要高度重视的一个问题,尤其是针对 Web 2.0 的应用.绝大多

随机推荐