iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >性能调优必备利器JMH优点有哪些
  • 236
分享到

性能调优必备利器JMH优点有哪些

2023-06-16 11:06:32 236人浏览 独家记忆
摘要

这篇文章主要介绍“性能调优必备利器JMH优点有哪些”,在日常操作中,相信很多人在性能调优必备利器JMH优点有哪些问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”性能调优必备利器JMH优点有哪些”的疑惑有所帮助!

这篇文章主要介绍“性能调优必备利器JMH优点有哪些”,在日常操作中,相信很多人在性能调优必备利器JMH优点有哪些问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”性能调优必备利器JMH优点有哪些”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

JMH 简介

JMH(Java Microbenchmark Harness)是用于代码微基准测试工具套件,主要是基于方法层面的基准测试,精度可以达到纳秒级。该工具是由 oracle 内部实现 JIT 的大牛们编写的,他们应该比任何人都了解 JIT 以及 JVM 对于基准测试的影响。

当你定位到热点方法,希望进一步优化方法性能的时候,就可以使用 JMH 对优化的结果进行量化的分析。

JMH 比较典型的应用场景如下:

  1.  想准确地知道某个方法需要执行多长时间,以及执行时间和输入之间的相关性

  2.  对比接口不同实现在给定条件下的吞吐量

  3.  查看多少百分比的请求在多长时间内完成

下面我们以字符串拼接的两种方法为例子使用 JMH 做基准测试。

加入依赖

因为 JMH 是 jdk9 自带的,如果是 JDK9 之前的版本需要加入如下依赖(目前 JMH 的最新版本为 1.23):

<dependency>      <groupId>org.openjdk.jmh</groupId>      <artifactId>jmh-core</artifactId>      <version>1.23</version>  </dependency>  <dependency>      <groupId>org.openjdk.jmh</groupId>      <artifactId>jmh-generator-annprocess</artifactId>      <version>1.23</version>  </dependency>

编写基准测试

接下来,创建一个 JMH 测试类,用来判断 + 和 StringBuilder.append() 两种字符串拼接哪个耗时更短,具体代码如下所示:

@BenchmarkMode(Mode.AverageTime)  @Warmup(iterations = 3, time = 1)  @Measurement(iterations = 5, time = 5)  @Threads(4)  @Fork(1)  @State(value = Scope.Benchmark)  @OutputTimeUnit(TimeUnit.NANOSECONDS)  public class StrinGConnectTest {      @Param(value = {"10", "50", "100"})      private int length;      @Benchmark      public void testStringAdd(Blackhole blackhole) {          String a = "";          for (int i = 0; i < length; i++) {              a += i;          }          blackhole.consume(a);      }      @Benchmark      public void testStringBuilderAdd(Blackhole blackhole) {          StringBuilder sb = new StringBuilder();          for (int i = 0; i < length; i++) {              sb.append(i);          }          blackhole.consume(sb.toString());      }      public static void main(String[] args) throws RunnerException {          Options opt = new OptionsBuilder()                  .include(StringConnectTest.class.getSimpleName())                  .result("result.JSON")                  .resultFORMat(ResultFormatType.jsON).build();          new Runner(opt).run();      }  }

其中需要测试的方法用 @Benchmark 注解标识,这些注解的具体含义将在下面介绍。

在 main() 函数中,首先对测试用例进行配置,使用 Builder 模式配置测试,将配置参数存入 Options 对象,并使用 Options 对象构造 Runner 启动测试。

另外大家可以看下官方提供的 jmh 示例 demo:s/src/main/java/org/openjdk/jmh/samples/" _fcksavedurl="Http://hg.openjdk.java.net/code-tools/jmh/file/tip/jmh-samples/src/main/java/org/openjdk/jmh/samples/">http://hg.openjdk.java.net/code-tools/jmh/file/tip/jmh-samples/src/main/java/org/openjdk/jmh/samples/

执行基准测试

准备工作做好了,接下来,运行代码,等待片刻,测试结果就出来了,下面对结果做下简单说明:

# JMH version: 1.23  # VM version: JDK 1.8.0_201, Java HotSpot(TM) 64-Bit Server VM, 25.201-b09  # VM invoker: D:\Software\Java\jdk1.8.0_201\jre\bin\java.exe  # VM options: -javaagent:D:\Software\JetBrains\IntelliJ idea 2019.1.3\lib\idea_rt.jar=61018:D:\Software\JetBrains\IntelliJ IDEA 2019.1.3\bin -Dfile.encoding=UTF-8 # Warmup: 3 iterations, 1 s each  # Measurement: 5 iterations, 5 s each  # Timeout: 10 min per iteration  # Threads: 4 threads, will synchronize iterations  # Benchmark mode: Average time, time/op  # Benchmark: com.wupx.jmh.StringConnectTest.testStringBuilderAdd  # Parameters: (length = 100)

该部分为测试的基本信息,比如使用的 Java 路径,预热代码的迭代次数,测量代码的迭代次数,使用的线程数量,测试的统计单位等。

# Warmup Iteration   1: 1083.569 &plusmn;(99.9%) 393.884 ns/op  # Warmup Iteration   2: 864.685 &plusmn;(99.9%) 174.120 ns/op  # Warmup Iteration   3: 798.310 &plusmn;(99.9%) 121.161 ns/op

该部分为每一次热身中的性能指标,预热测试不会作为最终的统计结果。预热的目的是让 JVM 对被测代码进行足够多的优化,比如,在预热后,被测代码应该得到了充分的 JIT 编译和优化。

Iteration   1: 810.667 &plusmn;(99.9%) 51.505 ns/op  Iteration   2: 807.861 &plusmn;(99.9%) 13.163 ns/op  Iteration   3: 851.421 &plusmn;(99.9%) 33.564 ns/op  Iteration   4: 805.675 &plusmn;(99.9%) 33.038 ns/op  Iteration   5: 821.020 &plusmn;(99.9%) 66.943 ns/op  Result "com.wupx.jmh.StringConnectTest.testStringBuilderAdd":    819.329 &plusmn;(99.9%) 72.698 ns/op [Average]    (min, avg, max) = (805.675, 819.329, 851.421), stdev = 18.879    CI (99.9%): [746.631, 892.027] (assumes normal distribution)  Benchmark                               (length)  Mode  Cnt     Score     Error  Units  StringConnectTest.testStringBuilderAdd       100  avgt    5   819.329 &plusmn;  72.698  ns/op

该部分显示测量迭代的情况,每一次迭代都显示了当前的执行速率,即一个操作所花费的时间。在进行 5 次迭代后,进行统计,在本例中,length 为 100 的情况下 testStringBuilderAdd 方法的平均执行花费时间为 819.329 ns,误差为 72.698 ns。

最后的测试结果如下所示:

Benchmark                               (length)  Mode  Cnt     Score     Error  Units  StringConnectTest.testStringAdd               10  avgt    5   161.496 &plusmn;  17.097  ns/op  StringConnectTest.testStringAdd               50  avgt    5  1854.657 &plusmn; 227.902  ns/op  StringConnectTest.testStringAdd              100  avgt    5  6490.062 &plusmn; 327.626  ns/op  StringConnectTest.testStringBuilderAdd        10  avgt    5    68.769 &plusmn;   4.460  ns/op  StringConnectTest.testStringBuilderAdd        50  avgt    5   413.021 &plusmn;  30.950  ns/op  StringConnectTest.testStringBuilderAdd       100  avgt    5   819.329 &plusmn;  72.698  ns/op

结果表明,在拼接字符次数越多的情况下,StringBuilder.append() 的性能就更好。

生成 jar 包执行

对于一些小测试,直接用上面的方式写一个 main 函数手动执行就好了。

对于大型的测试,需要测试的时间比较久、线程数比较多,加上测试的服务器需要,一般要放在 linux 服务器里去执行。

JMH 官方提供了生成 jar 包的方式来执行,我们需要在 Maven 里增加一个 plugin,具体配置如下:

<plugins>      <plugin>          <groupId>org.apache.maven.plugins</groupId>          <artifactId>maven-shade-plugin</artifactId>          <version>2.4.1</version>          <executions>              <execution>                  <phase>package</phase>                  <Goals>                      <goal>shade</goal>                  </goals>                  <configuration>                      <finalName>jmh-demo</finalName>                      <transformers>                          <transformer                                  implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">                              <mainClass>org.openjdk.jmh.Main</mainClass>                          </transformer>                      </transformers>                  </configuration>              </execution>          </executions>      </plugin>  </plugins>

接着执行 maven 的命令生成可执行 jar 包并执行:

mvn clean install  java -jar target/jmh-demo.jar StringConnectTest

JMH 基础

为了能够更好地使用 JMH 的各项功能,下面对 JMH 的基本概念进行讲解:

@BenchmarkMode

用来配置 Mode 选项,可用于类或者方法上,这个注解的 value 是一个数组,可以把几种 Mode 集合在一起执行,如:@BenchmarkMode({Mode.SampleTime, Mode.AverageTime}),还可以设置为 Mode.All,即全部执行一遍。

  1.  Throughput:整体吞吐量,每秒执行了多少次调用,单位为 ops/time

  2.  AverageTime:用的平均时间,每次操作的平均时间,单位为 time/op

  3.  SampleTime:随机取样,最后输出取样结果的分布

  4.  SingleShotTime:只运行一次,往往同时把 Warmup 次数设为 0,用于测试冷启动时的性能

  5.  All:上面的所有模式都执行一次

@State

通过 State 可以指定一个对象的作用范围,JMH 根据 scope 来进行实例化和共享操作。@State 可以被继承使用,如果父类定义了该注解,子类则无需定义。由于 JMH 允许多线程同时执行测试,不同的选项含义如下:

  1.  Scope.Benchmark:所有测试线程共享一个实例,测试有状态实例在多线程共享下的性能

  2.  Scope.Group:同一个线程在同一个 group 里共享实例

  3.  Scope.Thread:默认的 State,每个测试线程分配一个实例

@OutputTimeUnit

为统计结果的时间单位,可用于类或者方法注解

@Warmup

预热所需要配置的一些基本测试参数,可用于类或者方法上。一般前几次进行程序测试的时候都会比较慢,所以要让程序进行几轮预热,保证测试的准确性。参数如下所示:

  1.  iterations:预热的次数

  2.  time:每次预热的时间

  3.  timeUnit:时间的单位,默认秒

  4.  batchSize:批处理大小,每次操作调用几次方法

为什么需要预热?

因为 JVM 的 JIT 机制的存在,如果某个函数被调用多次之后,JVM 会尝试将其编译为机器码,从而提高执行速度,所以为了让 benchmark 的结果更加接近真实情况就需要进行预热。

@Measurement

实际调用方法所需要配置的一些基本测试参数,可用于类或者方法上,参数和 @Warmup 相同。

@Threads

每个进程中的测试线程,可用于类或者方法上。

@Fork

进行 fork 的次数,可用于类或者方法上。如果 fork 数是 2 的话,则 JMH 会 fork 出两个进程来进行测试。

@Param

指定某项参数的多种情况,特别适合用来测试一个函数在不同的参数输入的情况下的性能,只能作用在字段上,使用该注解必须定义 @State 注解。

在介绍完常用的注解后,让我们来看下 JMH 有哪些陷阱。

JMH 陷阱

在使用 JMH 的过程中,一定要避免一些陷阱。

比如 JIT 优化中的死码消除,比如以下代码:

@Benchmark  public void testStringAdd(Blackhole blackhole) {      String a = "";      for (int i = 0; i < length; i++) {          a += i;      }  }

JVM 可能会认为变量 a 从来没有使用过,从而进行优化把整个方法内部代码移除掉,这就会影响测试结果。

JMH 提供了两种方式避免这种问题,一种是将这个变量作为方法返回值 return a,一种是通过 Blackhole 的 consume 来避免 JIT 的优化消除。

其他陷阱还有常量折叠与常量传播、永远不要在测试中写循环、使用 Fork 隔离多个测试方法、方法内联、伪共享与缓存行、分支预测、多线程测试等,感兴趣的可以阅读 https://GitHub.com/lexburner/JMH-samples 了解全部的陷阱。

JMH 插件

大家还可以通过 IDEA 安装 JMH 插件使 JMH 更容易实现基准测试,在 IDEA 中点击 File->Settings...->Plugins,然后搜索 jmh,选择安装 JMH plugin:

性能调优必备利器JMH优点有哪些

JMH plugin

这个插件可以让我们能够以 JUnit 相同的方式使用 JMH,主要功能如下:

  1.  自动生成带有 @Benchmark 的方法

  2.  像 JUnit 一样,运行单独的 Benchmark 方法

  3.  运行类中所有的 Benchmark 方法

比如可以通过右键点击 Generate...,选择操作 Generate JMH benchmark 就可以生成一个带有 @Benchmark 的方法。

还有将光标移动到方法声明并调用 Run 操作就运行一个单独的 Benchmark 方法。

将光标移到类名所在行,右键点击 Run 运行,该类下的所有被 @Benchmark 注解的方法都会被执行。

JMH 可视化

除此以外,如果你想将测试结果以图表的形式可视化,可以试下这些网站:

  •  JMH Visual Chart:http://deepoove.com/jmh-visual-chart/

  •  JMH Visualizer:https://jmh.morethan.io/

比如将上面测试例子结果的 json 文件导入,就可以实现可视化:

性能调优必备利器JMH优点有哪些

到此,关于“性能调优必备利器JMH优点有哪些”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

--结束END--

本文标题: 性能调优必备利器JMH优点有哪些

本文链接: https://www.lsjlt.com/news/283372.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 性能调优必备利器JMH优点有哪些
    这篇文章主要介绍“性能调优必备利器JMH优点有哪些”,在日常操作中,相信很多人在性能调优必备利器JMH优点有哪些问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”性能调优必备利器JMH优点有哪些”的疑惑有所帮助!...
    99+
    2023-06-16
  • mysql性能调优方案有哪些
    MySQL性能调优方案有以下几种:1. 索引优化:通过合理创建和使用索引来提高查询性能。可以使用EXPLAIN语句来分析查询语句的执...
    99+
    2023-10-23
    mysql
  • MySQL性能调优之分区表的知识点有哪些
    本篇内容主要讲解“MySQL性能调优之分区表的知识点有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“MySQL性能调优之分区表的知识点有哪些”吧!对于用户而...
    99+
    2022-10-19
  • tomcat性能调优的技巧有哪些
    1. 增加JVM内存:通过调整Tomcat的启动参数,增加JVM的初始堆大小(-Xms)和最大堆大小(-Xmx),以提高Tomcat...
    99+
    2023-10-11
    tomcat
  • mysql性能调优的方法有哪些
    优化查询语句:使用合适的索引、避免使用全表扫描、避免使用不必要的子查询等。 优化数据模型:合理设计表结构,避免冗余字段和重复...
    99+
    2023-10-21
    mysql
  • Linux性能调优的方法有哪些
    今天小编给大家分享一下Linux性能调优的方法有哪些的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。1、为磁盘I/O调整Lin...
    99+
    2023-06-28
  • 免备案云服务器有哪些优点
    免备案云服务器的优点有:1、扩展性好,能有效解决传统物理主机与VPS服务中存在的管理难度大、业务扩展性弱的问题;2、能进行远程管理维护,实现云主机之间的完全隔离,且内置共享存储和智能备份;3、具有快速供应和部署的能力,支持平滑扩展,能快速实...
    99+
    2022-10-15
  • 免备案cdn服务器有哪些优点
    免备案cdn服务器的优点有:1、不用备案,能省去繁琐的备案过程和时间,直接使用;2、稳定性好,能减少网站单点故障;3、能智能的将用户...
    99+
    2023-02-08
    免备案cdn服务器 cdn服务器 服务器
  • Python性能调优的小技巧有哪些
    这篇文章主要为大家展示了“Python性能调优的小技巧有哪些”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Python性能调优的小技巧有哪些”这篇文章吧。1 多多使用列表生成式替换下面代码:cu...
    99+
    2023-06-25
  • 美国免备案服务器有哪些优点
    美国免备案服务器的优点有:1、有电信网直连网络带宽、联通直连网络带宽和归国cn2等CN2直连线路,稳定性好;2、不用备案,能为用户省去繁琐的备案过程;3、防御能力高,能够合理抵御DDOS、CC进攻;4、丢包率低,能提升数据的传输速度;5、网...
    99+
    2022-10-16
  • 免备案香港服务器有哪些优点
    免备案香港服务器的优点有:1、提供的带宽选择多,能实现全国访问,且访问速度快;2、机房技术处理先进,相关硬件配置好,能解决南电信北网通互连的问题;3、售后服务质量好,没有时差,能第一时间解决服务器故障问题。具体内容如下:带宽带宽好坏对于服务...
    99+
    2022-10-07
  • 香港免备案服务器有哪些优点
    香港免备案服务器的优点有:1、网站响应速度快,支持轻松处理突发的流量高峰负载,保证网站正常运行;2、可扩展性强,配置高,支持CPU、内存、硬盘等资源;3、操作简单,管理方便,可以使用任意所需的购物车软件有效的运行业务;4、安全性和稳定性高,...
    99+
    2022-10-11
  • Java性能调优的实用技巧有哪些
    这篇文章给大家分享的是有关Java性能调优的实用技巧有哪些的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。1.在必要之前,先不要优化 这可能是最最重要的性能调优技巧之一。你应该遵循常见的最佳实践,并尝试有效地实现你...
    99+
    2023-05-30
    java
  • 不用备案的云服务器有哪些优点
    不用备案的云服务器优点有:1、扩展性好,能解决传统物理主机和VPS主机管理难度大,业务扩展性弱的问题;2、支持远程维护管理,内置冗余的共享存储和智能备份功能,能实现数据间的完全隔离;3、具有快速供应和部署能力,支持业务平滑扩展,能快速实现业...
    99+
    2022-10-18
  • 无需备案的云服务器有哪些优点
    无需备案云服务器的的优点有:1、扩展好,能解决传统物理主机与VPS服务中管理难度大、业务扩展性弱的问题;2、支持远程管理维护,且内置共享存储和智能备份功能,能实现云主机之间数据的完全隔离;3、具有快速供应和部署的能力,支持平滑扩展,能快速实...
    99+
    2022-10-06
  • 香港服务器免备案有哪些优缺点
    香港服务器免备案的优缺点有:1、香港服务器免备案的优点有节省网站备案时间,解决了电信和网通之间通信难的问题,加快了亚太地区访问速度;2、香港服务器免备案的缺点是在做国际业务时想回国发展国内业务,则需要cdn加速网站,而这个过程则需要先备案才...
    99+
    2022-10-18
  • 免备案服务器租用有哪些优缺点
    免备案服务器租用的优缺点如下:优点:1. 无需备案,可快速上线。2. 无需担心备案被拒,节省时间和精力。3. 价格相对便宜,适合个人...
    99+
    2023-06-10
    免备案服务器 服务器
  • 国内免备案cdn服务器有哪些优点
    1. 无需备案:国内免备案CDN服务器无需备案,省去了备案的繁琐流程和时间成本,能够更快速地启动服务。2. 加速稳定:免备案CDN服...
    99+
    2023-06-05
    国内免备案cdn 国内cdn cdn
  • Java应用程序性能调优技巧有哪些
    这篇文章将为大家详细讲解有关Java应用程序性能调优技巧有哪些,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。大多数开发人员理所当然地以为性能优化很复杂,需要大量的经验和知识。好吧,不能说这是...
    99+
    2023-05-30
    java
  • Mysql性能有哪些调优与测试的方法
    本文主要给大家介绍Mysql性能有哪些调优与测试的方法,文章内容都是笔者用心摘选和编辑的,具有一定的针对性,对大家的参考意义还是比较大的,下面跟笔者一起了解下Mysql性能有哪些调优与测试的方法吧。一、关键...
    99+
    2022-10-18
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作