关于java性能调优的11个简单技巧

androidstarjack androidstarjack     2022-12-05     563

关键词:


 

点击上方关注 “终端研发部

设为“星标”,和你一起掌握更多数据库知识


源 / Java联盟

相信大多数的小伙伴都会觉着性能优化是一件很复杂的事,那么是不是呢?优化应用程序获得最佳性能并不是一件容易的事。它需要一定的经验和知识。

那么,我们现阶段还不具备这样的经验和知识,是不是就做不到了呢?也不是,以下就整理了11个实用技能,小伙伴们快来get吧~

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

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

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

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

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

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

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

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

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

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

希望不需要我解释为什么应该始终遵循第二种方法的原因。

很明显,基于分析器的方法可以让你更好地理解代码的性能影响,并使你能够专注于最关键的部分。

如果你曾使用过分析器,那么你一定记得曾经你是多么惊讶于一下就找到了代码的哪些部分产生了性能问题。老实说,我第一次的猜测不止一次地导致我走错了方向。

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

这是另一个通用技巧,可以帮助你避免在将性能改进部署到生产后经常会发生的许多意外问题。

你应该总是定义一个测试整个应用程序的性能测试套件,并在性能改进之前和之后运行它。

这些额外的测试运行将帮助你识别更改的功能和性能副作用,并确保不会导致弊大于利的更新。

如果你工作于被应用程序若干不同部分使用的组件,如数据库或缓存,那么这一点就尤其重要。

首先处理最大的瓶颈

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

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

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

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

使用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。这进一步提高了效率,因为它不需要动态扩展其容量。

使用+连接一个语句中的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,不需要连接。

尽可能使用基元

避免任何开销并提高应用程序性能的另一个简便而快速的方法是使用基本类型而不是其包装类。

所以,最好使用int来代替Integer,使用double来代替Double。这允许JVM将值存储在堆栈而不是堆中以减少内存消耗,并作出更有效的处理。

试着避免BigInteger和BigDecimal

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

BigInteger和BigDecimal比简单的long或double需要更多的内存,并且会显著减慢所有计算。

所以,你如果需要额外的精度,或者数字将超过long的范围,那么最好三思而后行。这可能是你需要更改以解决性能问题的唯一方法,特别是在实现数学算法的时候。

首先检查当前日志级别

这个建议应该是显而易见的,但不幸的是,很多程序员在写代码的时候都会大多会忽略它。

在你创建调试消息之前,始终应该首先检查当前日志级别。否则,你可能会创建一个之后会被忽略的日志消息字符串。

这里有两个反面例子。

// 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 + “]”);

使用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”);

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

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

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

你还可以在java语言本身找到其他例子。例如,Integer类的valueOf方法缓存了-128到127之间的值。

你可能会说创建一个新的Integer并不是太昂贵,但是由于它经常被使用,以至于缓存最常用的值也可以提供性能优势。

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

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

总结

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

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

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

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

首先处理最大的瓶颈

最后说一句(别白嫖,求关注)

回复 【idea激活】即可获得idea的激活方式
回复 【Java】获取java相关的视频教程和资料
回复 【SpringCloud】获取SpringCloud相关多的学习资料
回复 【python】获取全套0基础Python知识手册
回复 【2020】获取2020java相关面试题教程
回复 【加群】即可加入终端研发部相关的技术交流群
阅读更多
用 Spring 的 BeanUtils 前,建议你先了解这几个坑!

lazy-mock ,一个生成后端模拟数据的懒人工具

在华为鸿蒙 OS 上尝鲜,我的第一个“hello world”,起飞!

字节跳动一面:i++ 是线程安全的吗?

一条 SQL 引发的事故,同事直接被开除!!

太扎心!排查阿里云 ECS 的 CPU 居然达100%

一款vue编写的功能强大的swagger-ui,有点秀(附开源地址)


相信自己,没有做不到的,只有想不到的在这里获得的不仅仅是技术!



喜欢就给个“在看”

关于linux性能调优中磁盘io调优的一些笔记(代码片段)

写在前面和小伙伴分享一些Linux磁盘IO优化的笔记,内容很浅,可以用作入门博文内容结合《Linux性能优化》读书笔记整理涉及内容包括使用vmstat统计系统内磁盘分区I/O属性的性能使用iostat分析磁盘分区的饱和度,利用率... 查看详情

9个java性能调优技巧,yyds!

...”,和你一起掌握更多数据库知识大多数开发者认为性能优化是一个复杂的话题,它需要大量的工作经验和相关知识理论。好吧,这也不完全错。优化一个应用做到性能最优化可能不是件容易的任务,但是这并不... 查看详情

hive参数与性能企业级调优(代码片段)

...架之一。但是如果我们只局限于会使用Hive,而不考虑性能问题,就难搭建出一个完美的数仓,所以Hive性能调优是我们大数据从业者必须掌握的技能。本文将给大家讲解Hive性能调优的一些方法及技巧。Hive性能调优的... 查看详情

关于linux性能调优之内存负载调优(代码片段)

写在前面整理一些Linux内存调优的笔记,分享给小伙伴博文没有涉及的Demo,理论方法偏多,可以用作内存调优入门博文内容涉及:Linux内存管理的基本理论寻找内存泄露的进程内存交换空间调优不同方式的内存回收食用方式... 查看详情

day707.jetty性能调优的思路-深入拆解tomcat&jetty(代码片段)

...性能调优的思路Hi,我是阿昌,今天学习记录的是关于Jetty性能调优的思路一、操作系统层面调优对于Linux操作系统调优来说,我们需要加大一些默认的限制值,这些参数主要可以在/etc/security/limits.conf中或通过sysctl... 查看详情

真实世界的 Clojure 性能调优技巧?

...我看到Clojure应用程序的“某些”部分出现严重的减速。关于如何对clojure应用程序进行性能调优,有人有任何现实世界的提示吗?【问题讨论】:【参考方案1】:我的个人建议:首先检查你的算法-你是否会产生O(n^2)成本,而实... 查看详情

关于linux中系统调优的一些笔记(代码片段)

写在前面推送的的邮件里看到有大佬讲的公共课,听了之后这里整理学习笔记。因为是公开课,所以讲的很浅,没接触过,这里做为了解,长长见识。博文内容包括系统调优原理概述如何检测系统的性能瓶颈... 查看详情

关于linux性能调优之内存负载调优(代码片段)

写在前面整理一些Linux内存调优的笔记,分享给小伙伴博文没有涉及的Demo,理论方法偏多,可以用作内存调优入门博文内容涉及:Linux内存管理的基本理论寻找内存泄露的进程内存交换空间调优不同方式的内存回收食用方式... 查看详情

mysql性能调优和优化技巧(代码片段)

...0c;庞大的数据量可能会导致性能问题。本指南提供了一些关于如何提高MySQL数据库性能的调优技巧。先决条件安装并运行MySQL的Linux系统,Centos或Ubuntu现有数据库操作系统和数据库的管理员凭据系统MySQL性能调优在系统级别ÿ... 查看详情

性能调优调优的常见思路和方法(代码片段)

...和调优?在这里提供一些可实践、可借鉴、可参考的性能调优套路,即:如何在众多异常性能指标中,找出最核心的那一个,进而定位性能瓶颈点,最后进行性能调优以下会按照代码、CPU、内存、网络、磁... 查看详情

性能测试知多少---性能分析与调优的原理

最近一直纠结性能分析与调优如何下手,先从硬件开始,还是先从代码或数据库。从操作系统(CPU调度,内存管理,进程调度,磁盘I/O)、网络、协议(HTTP, TCP/IP ),还是从应用程序代码,数据库调优,中间件配置等... 查看详情

hive参数与性能企业级调优(代码片段)

...架之一。但是如果我们只局限于会使用Hive,而不考虑性能问题,就难搭建出一个完美的数仓,所以Hive性能调优是我们大数据从业者必须掌握的技能。本文将给大家讲解Hive性能调优的一些方法及技巧。Hive性能调优的... 查看详情

hive参数与性能企业级调优(代码片段)

...架之一。但是如果我们只局限于会使用Hive,而不考虑性能问题,就难搭建出一个完美的数仓,所以Hive性能调优是我们大数据从业者必须掌握的技能。本文将给大家讲解Hive性能调优的一些方法及技巧。Hive性能调优的... 查看详情

hive参数与性能企业级调优(代码片段)

...架之一。但是如果我们只局限于会使用Hive,而不考虑性能问题,就难搭建出一个完美的数仓,所以Hive性能调优是我们大数据从业者必须掌握的技能。本文将给大家讲解Hive性能调优的一些方法及技巧。Hive性能调优的... 查看详情

Haskell 性能提升的简单技巧(关于 ProjectEuler 问题)?

】Haskell性能提升的简单技巧(关于ProjectEuler问题)?【英文标题】:SimpletipsforHaskellperformanceincreases(onProjectEulerproblems)?【发布时间】:2012-07-1323:17:30【问题描述】:我是通过阅读和解决ProjectEuler问题来编程和学习Haskell的新手。... 查看详情

jvm性能调优

JVM性能调优JVM垃圾回收与性能调优总结JVM调优的几种策略 650)this.width=650;"src="http://dl2.iteye.com/upload/attachment/0101/2383/3d11dfb9-18ca-32f6-8e45-48522c670e92.jpeg"title="点击查看原始大小图片"class="magplus"width="700"hei 查看详情

etl调优的一些分享(下)(转载)

...》中已介绍的,ETL是构建数据仓库的必经一环,它的执行性能对于数据仓库构建性能有重要意义,因此对它进行有效的调优将十分重要。ETL业务的调优可以从若干思路开展,上文我们已经介绍了其中三点,本文我们将再分享如下... 查看详情

java性能调优实战网盘,附小技巧

1、PTP模型Point-to-Point,点对点通信模型。PTP是基于队列(Queue)的,一个队列可以有多个生产者,和多个消费者。消息服务器按照收到消息的先后顺序,将消息放到队列中。队列中的每一条消息,只能由一个消费... 查看详情