一、前言
在日常開(kāi)發(fā)工作當(dāng)中,開(kāi)發(fā)人員可能有這些困惑:自己寫(xiě)的這個(gè)方法性能到底怎么樣?在原接口實(shí)現(xiàn)方法中添加了新的業(yè)務(wù)邏輯,對(duì)整個(gè)接口的性能影響有多少?有多種實(shí)現(xiàn)方式(或開(kāi)源類(lèi)庫(kù)),到底哪一種性能更好?
當(dāng)遇到類(lèi)似困惑或者說(shuō)問(wèn)題的時(shí)候,怎么辦呢?當(dāng)然是測(cè)試驗(yàn)證,實(shí)踐出真知!本文講述的就是一個(gè)方法級(jí)別的性能測(cè)試工具—— JMH。
二、JMH概述
1、什么是JMH
JMH,即 Java Microbenchmark Harness,是專(zhuān)門(mén)用于代碼微基準(zhǔn)測(cè)試的工具套件。何謂Micro Benchmark呢?簡(jiǎn)單的來(lái)說(shuō)就是基于方法層面的基準(zhǔn)測(cè)試,精度可以達(dá)到微秒級(jí)。其由 Oracle/openjdk 內(nèi)部開(kāi)發(fā)JIT編譯器的大佬們所開(kāi)發(fā),作為java的方法級(jí)性能測(cè)試工具可以說(shuō)是根正苗紅了。(官方地址:http://hg.openjdk.java.net/code-tools/jmh/ )
2、JMH適用的典型場(chǎng)景
- a、優(yōu)化熱點(diǎn)方法,準(zhǔn)確的知道某個(gè)方法的執(zhí)行耗時(shí),以及不同入?yún)⑴c最終實(shí)際耗時(shí)的關(guān)系,從而針對(duì)性的進(jìn)行優(yōu)化;
- b、尋找最佳方案,驗(yàn)證接口方法不同實(shí)現(xiàn)方式的實(shí)際吞吐量,從而確定最佳實(shí)現(xiàn)方式 。如:選擇json轉(zhuǎn)換工具時(shí)選fastjson還是gson、字符串連接使用StringBuilder方式還是直接相加;
- c、分析性能損耗,在原接口方法業(yè)務(wù)邏輯中添加新的業(yè)務(wù)代碼時(shí),對(duì)整個(gè)業(yè)務(wù)方法的性能影響。如:在原業(yè)務(wù)邏輯中,添加一個(gè)插入操作日志的操作,可以分析新加操作對(duì)整個(gè)業(yè)務(wù)方法的性能影響。
- d、分析百分比內(nèi)的耗時(shí),即測(cè)試方法多次調(diào)用時(shí)百分比區(qū)間內(nèi)的耗時(shí),如:測(cè)試調(diào)用某個(gè)方法,50%以?xún)?nèi)的調(diào)用耗時(shí)是8.2ms/op,90%以?xún)?nèi)是9.3ms/op,99.99%以?xún)?nèi)是10.2ms/op,等等。(模式為Mode.SampleTime)
3、JMH基本概念
- a、Mode :表示JMH測(cè)試中的模式,默認(rèn)有5種,分別是Throughput(吞吐量)、AverageTime(平均耗時(shí))、SampleTime(隨機(jī)采樣)、SingleShotTime(單次執(zhí)行)、All(以上4種都來(lái)一次);
- b、Fork:表示JMH將用來(lái)測(cè)試的進(jìn)程數(shù);
- c、Warmup : 表示預(yù)熱,在HotSpot中,JVM的JIT編譯器會(huì)對(duì)熱點(diǎn)代碼進(jìn)行編譯優(yōu)化, 因此為了最接近真實(shí)的情況,需要先預(yù)熱測(cè)試代碼,使JIT編譯器完成可能需要的優(yōu)化,從而令JMH最終測(cè)試結(jié)果更加準(zhǔn)確;
- d、Iteration :表示JMH中的最小測(cè)試迭代單位,即測(cè)試次數(shù),一般默認(rèn)值是每次1s;
- e、Benchmark:用于標(biāo)注JMH將進(jìn)行測(cè)試的方法。(類(lèi)似Junit中的@Test注解)
三、示例
1、添加依賴(lài)
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>1.36</version>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>1.36</version>
<scope>provided</scope>
</dependency>
2、示例代碼
package com.example.springbootdemo1;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Threads;
import org.openjdk.jmh.annotations.Warmup;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
import java.util.concurrent.TimeUnit;
/**
* try - catch 性能測(cè)試
*/
@BenchmarkMode(Mode.AverageTime) // 測(cè)試完成時(shí)間
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 1, time = 1, timeUnit = TimeUnit.SECONDS) // 預(yù)熱 1 輪,每次 1s
@Measurement(iterations = 5, time = 5, timeUnit = TimeUnit.SECONDS) // 測(cè)試 5 輪,每次 3s
@Fork(1) // fork 1 個(gè)線(xiàn)程
@State(Scope.Benchmark)
@Threads(100)
public class TryCatchPerformanceTest {
private static final int forSize = 1000; // 循環(huán)次數(shù)
public static void main(String[] args) throws RunnerException {
// 啟動(dòng)基準(zhǔn)測(cè)試
Options opt = new OptionsBuilder().include(TryCatchPerformanceTest.class.getSimpleName()) // 要導(dǎo)入的測(cè)試類(lèi)
.build();
new Runner(opt).run(); // 執(zhí)行測(cè)試
}
@Benchmark
public int innerForeach() {
int count = 0;
for (int i = 0; i < forSize; i++) {
try {
if (i == forSize) {
throw new Exception("new Exception");
}
count++;
} catch (Exception e) {
e.printStackTrace();
}
}
return count;
}
@Benchmark
public int outerForeach() {
int count = 0;
try {
for (int i = 0; i < forSize; i++) {
if (i == forSize) {
throw new Exception("new Exception");
}
count++;
}
} catch (Exception e) {
e.printStackTrace();
}
return count;
}
}
代碼拷貝就可以直接運(yùn)行,其他更多測(cè)試請(qǐng)自行修改試驗(yàn)。
參考:https://www.uoften.com/article/215076.html文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-722900.html
(END)文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-722900.html
到了這里,關(guān)于JMH - Java代碼基準(zhǔn)測(cè)試工具,代碼性能問(wèn)題驗(yàn)證測(cè)試的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!