使用JMH框架進行性能基準測試

介紹

我們在選擇不同框架、算法時,不同場景下的性能是很重要考慮因素。JMH這個Java的微基準測試框架提供簡單的方式來實現性能測試的需求。本文將以一個對比序列化器性能的例子簡單介紹JMH的使用。

創建項目

不同于 JUnit 這種測試框架,JMH推薦創建獨立的項目來做測試。

使用maven創建

mvn archetype:generate \
-DinteractiveMode=false \
-DarchetypeGroupId=org.openjdk.jmh \
-DarchetypeArtifactId=jmh-java-benchmark-archetype \
-DgroupId=org.sample \
-DartifactId=test \
-Dversion=1.0

執行命令后生成項目

IDEA中創建項目

除了maven命令直接創建之外,也可以選擇在IDE中創建maven,以IDEA為例。

在創建項目時,選擇Maven項目,勾選 Create from archetype 并選擇 Add Archetype...

在彈出的窗口中填入對應信息(當前最新版本為1.33)

增加archetype

之后就可以選擇JMH的archetype在IDEA中創建項目了。

編寫測試代碼

項目自動生成的 pom.xml 文件中已經包含JMH運行最小依賴了,只需要加上待測試相關的依賴包。這里我要測試的是 spring-data-redis 中序列化對象相關的內容,因此需要添加以下依賴:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <version>2.1.1.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.12.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.12.3</version>
</dependency>

之后編寫測試代碼,這里我使用了對比了 ObjectHashMapperJackson2HashMapper 兩個類的 toHash 方法平均調用時間。預熱5輪,實際測試5輪并fork 5 個進程來進行測試。

@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 5, time = 1)
@Measurement(iterations = 5, time = 1)
@Fork(5)
@State(Scope.Benchmark)
public class MyBenchmark {

private HashMapper objectHashMapper;
 private HashMapper jacksonHashMapper;

 @Setup
 public void setup() {
    objectHashMapper = new ObjectHashMapper();
 jacksonHashMapper = new Jackson2HashMapper(false);
 }

@Benchmark
 public void testObjectHashMapper() {
    SesAnswerRate answerRatePredictor = new SesAnswerRate(0.3F, 0.5F);
 objectHashMapper.toHash(answerRatePredictor);
 }

@Benchmark
 public void testJacksonHashMapper() {
    SesAnswerRate answerRatePredictor = new SesAnswerRate(0.3F, 0.5F);
 jacksonHashMapper.toHash(answerRatePredictor);
 }

public static void main(String[] args) throws RunnerException {
    Options options = new OptionsBuilder()
            .include(MyBenchmark.class.getSimpleName())
            .build();
 new Runner(options).run();
 }
}

建議IDEA用戶安裝idea-jmh-plugin插件,便于運行測試。

執行測試

如果沒有安裝IDE插件,可以執行 mvn clean package 打包,之后在項目下的target文件夾中執行 java -jar benchmarks.jar 運行。

最終運行結果如下:

Benchmark                          Mode  Cnt     Score     Error  Units
MyBenchmark.testJacksonHashMapper  avgt   25   536.386 ±  25.589  ns/op
MyBenchmark.testObjectHashMapper   avgt   25  1601.561 ± 139.910  ns/op

可以看到使用 Jackson2HashMapper 序列化對象的速度要比 ObjectHashMapper 快上3倍。

總結

可以看到利用JMH能夠快速編寫,運行測試代碼,對于method級別的性能測試非常有用,篇幅所限在此不展開講述更加具體的用法。

建議有需要的同學們閱讀官方示例: jmh-samples

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容