詳解Java使用JMH進行基準性能測試
一、前言
在日常開發工作當中,開發人員可能有這些困惑:自己寫的這個方法性能到底怎麼樣?在原接口實現方法中添加瞭新的業務邏輯,對整個接口的性能影響有多少?有多種實現方式(或開源類庫),到底哪一種性能更好?…
當遇到類似困惑或者說問題的時候,怎麼辦呢?當然是測試驗證,實踐出真知!本文講述的就是一個方法級別的性能測試工具——JMH。
二、JMH概述
1、什麼是JMH
JMH,即Java Microbenchmark Harness,是專門用於代碼微基準測試的工具套件。何謂Micro Benchmark呢?簡單的來說就是基於方法層面的基準測試,精度可以達到微秒級。其由Oracle/openjdk內部開發JIT編譯器的大佬們所開發,作為java的方法級性能測試工具可以說是根正苗紅瞭。(官方地址:http://hg.openjdk.java.net/code-tools/jmh/ )
2、JMH適用的典型場景
a、優化熱點方法,準確的知道某個方法的執行耗時,以及不同入參與最終實際耗時的關系,從而針對性的進行優化;
b、尋找最佳方案,驗證接口方法不同實現方式的實際吞吐量,從而確定最佳實現方式 。如:選擇json轉換工具時選fastjson還是gson、字符串連接使用StringBuilder方式還是直接相加;
c、分析性能損耗,在原接口方法業務邏輯中添加新的業務代碼時,對整個業務方法的性能影響。如:在原業務邏輯中,添加一個插入操作日志的操作,可以分析新加操作對整個業務方法的性能影響。
d、分析百分比內的耗時,即測試方法多次調用時百分比區間內的耗時,如:測試調用某個方法,50%以內的調用耗時是8.2ms/op,90%以內是9.3ms/op,99.99%以內是10.2ms/op,等等。(模式為Mode.SampleTime)
3、JMH基本概念
a、Mode :表示JMH測試中的模式,默認有5種,分別是Throughput(吞吐量)、AverageTime(平均耗時)、SampleTime(隨機采樣)、SingleShotTime(單次執行)、All(以上4種都來一次);
b、Fork:表示JMH將用來測試的進程數;
c、Warmup : 表示預熱,在HotSpot中,JVM的JIT編譯器會對熱點代碼進行編譯優化, 因此為瞭最接近真實的情況,需要先預熱測試代碼,使JIT編譯器完成可能需要的優化,從而令JMH最終測試結果更加準確;
d、Iteration :表示JMH中的最小測試迭代單位,即測試次數,一般默認值是每次1s;
e、Benchmark:用於標註JMH將進行測試的方法。(類似Junit中的@Test註解)
三、JMH的使用
1、快速跑起來
JMH的基本使用隻需2步,第1步是引入maven依賴包,第2步是根據工具框架模板編寫測試類,以下通過一個簡單例子進行詳細說明:
例1:測試一個方法的平均耗時
第1步:引入maven依賴: (筆者使用的jmh版本為1.21)
<!-- JMH --> <dependency> <groupId>org.openjdk.jmh</groupId> <artifactId>jmh-core</artifactId> <version>${jmh.version}</version> </dependency> <dependency> <groupId>org.openjdk.jmh</groupId> <artifactId>jmh-generator-annprocess</artifactId> <version>${jmh.version}</version> <scope>provided</scope> </dependency>
第2步:編寫測試方法:
package com.xiaojiang; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Mode; import org.openjdk.jmh.annotations.OutputTimeUnit; import org.openjdk.jmh.runner.Runner; import org.openjdk.jmh.runner.options.Options; import org.openjdk.jmh.runner.options.OptionsBuilder; import java.util.concurrent.TimeUnit; /** * @ Description:jmh使用第一個例子 * @ Author :xiaojiang * @ Date :Created in 2019-06-19 * @ Version :0.0.1 */ @OutputTimeUnit(TimeUnit.MILLISECONDS) @BenchmarkMode(Mode.AverageTime) public class JmhDemoOne { public static void main(String[] args) throws Exception{ Options options = new OptionsBuilder() .include(JmhDemoOne.class.getName()) .build(); new Runner(options).run(); } /** * 測試sayHello的平局耗時 * * @throws Exception */ @Benchmark public void sayHello() throws Exception{ //TODO 業務方法 ,此處用休眠的方式模擬業務耗時10 ms TimeUnit.MILLISECONDS.sleep(10); } }
代碼說明:
通過以上例子可以發現,一個基本的JMH測試實現其實並不是很復雜,非常類似於用Junit做單元測試。具體說明如下:
a、類名JmhDemoOne 上的@OutputTimeUnit、@BenchmarkMode這兩個註解,表明這是一個JMH的測試類;(具體註解含義 ,以及更多註解說明請參考下文JMH常用註解詳細介紹)
b、主函數入口main方法中指定瞭一些基本測試參數選項;(基本就是固定寫法。其實有更多相關參數方法可以添加,但這些參數筆者建議通過註解的方式在類上直接添加,這樣來的更加方便)
c、通過@Benchmark註解標註需要benchmark(基準測試)的具體方法;
直接運行測試方法,控制臺輸出測試結果如下:(筆者JDK版本為1.8,IDE工具為IDEA2018)
# JMH version: 1.21 # VM version: JDK 1.8.0_144, Java HotSpot(TM) 64-Bit Server VM, 25.144-b01 # VM invoker: D:\Java\jdk1.8.0_144\jre\bin\java.exe # VM options: -javaagent:D:\Program Files\JetBrains\IntelliJ IDEA 2018.2.5\lib\idea_rt.jar=55987:D:\Program Files\JetBrains\IntelliJ IDEA 2018.2.5\bin -Dfile.encoding=UTF-8 # Warmup: 5 iterations, 10 s each # Measurement: 5 iterations, 10 s each # Timeout: 10 min per iteration # Threads: 1 thread, will synchronize iterations # Benchmark mode: Average time, time/op # Benchmark: com.xiaojiang.JmhDemoOne.sayHello # Run progress: 0.00% complete, ETA 00:08:20 # Fork: 1 of 5 # Warmup Iteration 1: 10.716 ms/op # Warmup Iteration 2: 10.640 ms/op # Warmup Iteration 3: 10.737 ms/op # Warmup Iteration 4: 10.693 ms/op # Warmup Iteration 5: 10.723 ms/op Iteration 1: 10.716 ms/op Iteration 2: 10.724 ms/op Iteration 3: 10.772 ms/op Iteration 4: 10.758 ms/op Iteration 5: 10.709 ms/op # Run progress: 20.00% complete, ETA 00:06:43 # Fork: 2 of 5 # Warmup Iteration 1: 10.744 ms/op # Warmup Iteration 2: 10.732 ms/op # Warmup Iteration 3: 10.748 ms/op # Warmup Iteration 4: 10.728 ms/op # Warmup Iteration 5: 10.760 ms/op Iteration 1: 10.701 ms/op Iteration 2: 10.709 ms/op Iteration 3: 10.719 ms/op Iteration 4: 10.714 ms/op Iteration 5: 10.703 ms/op # Run progress: 40.00% complete, ETA 00:05:02 # Fork: 3 of 5 # Warmup Iteration 1: 10.729 ms/op # Warmup Iteration 2: 10.731 ms/op # Warmup Iteration 3: 10.728 ms/op # Warmup Iteration 4: 10.700 ms/op # Warmup Iteration 5: 10.709 ms/op Iteration 1: 10.708 ms/op Iteration 2: 10.701 ms/op Iteration 3: 10.708 ms/op Iteration 4: 10.726 ms/op Iteration 5: 10.698 ms/op # Run progress: 60.00% complete, ETA 00:03:21 # Fork: 4 of 5 # Warmup Iteration 1: 10.724 ms/op # Warmup Iteration 2: 10.688 ms/op # Warmup Iteration 3: 10.748 ms/op # Warmup Iteration 4: 10.732 ms/op # Warmup Iteration 5: 10.772 ms/op Iteration 1: 10.729 ms/op Iteration 2: 10.688 ms/op Iteration 3: 10.705 ms/op Iteration 4: 10.687 ms/op Iteration 5: 10.709 ms/op # Run progress: 80.00% complete, ETA 00:01:40 # Fork: 5 of 5 # Warmup Iteration 1: 10.688 ms/op # Warmup Iteration 2: 10.696 ms/op # Warmup Iteration 3: 10.692 ms/op # Warmup Iteration 4: 10.684 ms/op # Warmup Iteration 5: 10.683 ms/op Iteration 1: 10.719 ms/op Iteration 2: 10.720 ms/op Iteration 3: 10.695 ms/op Iteration 4: 10.710 ms/op Iteration 5: 10.760 ms/op Result "com.xiaojiang.JmhDemoOne.sayHello": 10.716 ±(99.9%) 0.016 ms/op [Average] (min, avg, max) = (10.687, 10.716, 10.772), stdev = 0.021 CI (99.9%): [10.700, 10.731] (assumes normal distribution) # Run complete. Total time: 00:08:24 REMEMBER: The numbers below are just data. To gain reusable insights, you need to follow up on why the numbers are the way they are. Use profilers (see -prof, -lprof), design factorial experiments, perform baseline and negative tests that provide experimental control, make sure the benchmarking environment is safe on JVM/OS/HW level, ask for reviews from the domain experts. Do not assume the numbers tell you what you want them to tell. Benchmark Mode Cnt Score Error Units JmhDemoOne.sayHello avgt 25 10.716 ± 0.016 ms/op Process finished with exit code 0
測試結果說明:
整個測試結果分為3大塊,測試基本參數信息、測試過程、測試結果,各行含義具體說明如下:
塊 | 說明 |
---|---|
參數信息(1-10行) | 1:jmh版本 2:jvm版本信息 3:jvm程序(jdk安裝路徑) 4:jvm參數配置 5:預熱參數:預熱次數、每次持續時間 6:測試參數:測試次數、每次持續時間 7:每次測試迭代超時時間 8:每個測試進程的測試線程數 9: 測試的模式 10:測試的方法 |
測試過程(12-75行) | 12-23:第1次fork測試 (fork可以理解為1個獨立的進程) 12:測試完成進度,預計剩餘需要時間 13:當前第幾次fork 14-18:預熱執行,每次預熱執行耗時 19-23:正式測試執行,每次測試執行耗時 25-36:第2次fork測試 38-49:第3次fork測試 51-62:第4次fork測試 64-75:第5次fork測試 |
測試結果(78-95行) | 78-81:測試結果,包括測試的方法、平均耗時[平局耗時的比例]、最大最小 耗時、測試結果數據離散度(stdev)等 84:測試總耗時 86-90:對測試結果的解釋 92-93:測試結論{測試的方法、測試類型(Mode)、測試總次數(Cnt)、測試結果(Score)、誤差(Error)、單位(Units)} 95:結束 |
註:
a、測試結果中的Measurement、Fork、Warmup等參數,是JMH采用瞭默認的配置值,實際使用中,我們可根據需要指定相關參數。
b、運行這個測試類可以在IDEA中直接跑,也可以打成 jar 包到服務器上跑。
c、本測試結果是直接輸出在控制臺,如有需要,可將測試結果輸出到文件中,方法是在options中添加output方法指定測試結果輸出目錄,如下:
Options options = new OptionsBuilder() .include(JmhDemoOne.class.getName()) .output("D:/JmhDemoOne.log") //將測試結果輸出到指定目錄文件 .build();
2、JMH常用註解詳細介紹
註解 | 介紹 |
---|---|
@BenchmarkMode | 基準測試模式。一共有5種可選值:(其實是4種) Mode.Throughput:吞吐量模式,即單位時間內方法的吞吐量 Mode.AverageTime:平均耗時模式,即一定測試次數內方法執行的平均耗時 Mode.SampleTime:隨機采樣模式,即最終結果為取樣結果分佈比例 Mode.SingleShotTime:單次執行模式,即隻會執行一次(以上的模式通常會有預熱、會迭代執行多次,這個模式可用於測試某些特定場景,如冷啟動時的性能) Mode.All:即以上模式都執行一遍 ———————————– |
@OutputTimeUnit | 測試結果的時間單位。其值為java.util.concurrent.TimeUnit 枚舉中的值,通常用的值是秒、毫秒、微妙(需要註意的是,在不同測試模式下,需要選擇合適的時間單位,從而獲取更精確的測試結果。)
———————————— |
@Benchmark | 基準測試,方法級註解(配置在方法名上)。用於標註需要進行benchmark (基準測試)的方法
———————————— |
@Warmup | 預熱參數。配置預熱的相關參數,參數含義是:iterations(預熱次數)、time (預熱時間)、timeUnit (時間單位)
———————————— |
@Measurement | 度量,即benchmark基本參數。參數含義是:iterations(測試次數)、time (每次測試時間)、timeUnit (時間單位)
———————————— |
@Fork | 分叉,即進程數。用於配置將使用多少個進程進行測試
———————————— |
@Threads | 線程數。每個Fork(進程)中的線程數,一般可設為測試機器cpu核心數。
———————————— |
@Param | 成員參數,屬性級註解。用於測試方法在不同入參情況下的性能表現。
———————————— |
@Setup | 設置,方法級註解。用於標註benchmark前的操作,通常用於測試前初始化參數資源,如初始化數據庫連接等。
———————————— |
@TearDown | 拆卸,方法級註解。用於標註benchmark後的操作,通常用於測試後回收資源,如關閉數據庫連接等。
———————————— |
@State | 狀態,表示一個類/方法的可用范圍,其值有3個: Scope.Thread:默認狀態,每個線程分配一個獨享的實例; Scope.Benchmark:測試中的所有線程共享實例;(多線程測試情況下) Scope.Group:同一個組的線程共享實例; ———————————— |
@Group | 測試組,方法級註解。適用分組測試,每組線程數不一樣的場景。
———————————— |
@GroupThreads | 組線程數,方法級註解。通常和@Group搭配使用
———————————— |
@Timeout | 超時時間。每次測試迭代超時時間
———————————— |
以上是使用JMH測試中常用的註解,當然JMH還有一些其它註解,如@CompilerControl、@AuxCounters 等等,這些註解通常可用於滿足特定的測試場景需求,具體相關使用如有需要,可參考官方示例,官方demo比較詳細,比較好理解學習。
3、更多示例
本小節筆者將通過幾個小示例,展示JMH的基本使用。
例2:
測試驗證字符串連接處理時,使用StringBuilder方式是否比直接相加好。
package com.xiaojiang; import org.openjdk.jmh.annotations.*; import org.openjdk.jmh.runner.Runner; import org.openjdk.jmh.runner.options.Options; import org.openjdk.jmh.runner.options.OptionsBuilder; import java.util.concurrent.TimeUnit; /** * @ Description:jmh使用第二個例子 * @ Author :xiaojiang * @ Date :Created in 2019-06-19 * @ Version :0.0.1 */ @OutputTimeUnit(TimeUnit.SECONDS) @BenchmarkMode(Mode.Throughput) @Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.MILLISECONDS) @Measurement(iterations = 10, time = 5, timeUnit = TimeUnit.SECONDS) @State(Scope.Thread) public class JmhDemoTwo { public static void main(String[] args) throws Exception{ Options options = new OptionsBuilder() .include(JmhDemoTwo.class.getName()) .build(); new Runner(options).run(); } /** * 字符串個數 */ @Param({"10", "100", "1000"}) private int number; /** * 字符串直接相加方式 */ @Benchmark public void StringAddMode(){ String str = ""; for(int i=0;i<number;i++){ str = str + i; } } /** * 字符串通過StringBuilder的append方式 */ @Benchmark public void StringBuilderMode(){ StringBuilder sb = new StringBuilder(); for(int i=0;i<number;i++){ sb.append(i); } } }
測試結果:
//—省略測試過程結果———-
Benchmark (number) Mode Cnt Score Error Units
JmhDemoTwo.StringAddMode 10 thrpt 50 7670608.558 ± 99068.181 ops/s
JmhDemoTwo.StringAddMode 100 thrpt 50 437133.436 ± 7738.031 ops/s
JmhDemoTwo.StringAddMode 1000 thrpt 50 4023.846 ± 62.872 ops/s
JmhDemoTwo.StringBuilderMode 10 thrpt 50 22608867.036 ± 669332.843 ops/s
JmhDemoTwo.StringBuilderMode 100 thrpt 50 1232847.661 ± 23742.088 ops/s
JmhDemoTwo.StringBuilderMode 1000 thrpt 50 98367.745 ± 1487.840 ops/s
從測試結果可以看出,在字符串連接數量分別為10、100、1000時,通過StringBuilder處理字符串的方式比直接相加的方式性能都要強一些;如,當字符竄數量為1000時,直接相加方式的方法吞吐量為4023.846 ops/s,StringBuilder的方式方法吞吐量達到 98367.745ops/s 。(當然具體測試結果值和機器配置、JVM配置有關)
例3:
測試常用序列化json庫fastJson、gson、jackson的性能(均為截止2019.06最新版本)。
package com.xiaojiang; import org.openjdk.jmh.annotations.*; import org.openjdk.jmh.runner.Runner; import org.openjdk.jmh.runner.options.Options; import org.openjdk.jmh.runner.options.OptionsBuilder; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.concurrent.TimeUnit; /** * @ Description:jmh使用第三個例子 * @ Author :xiaojiang * @ Date :Created in 2019-06-19 * @ Version :0.0.1 */ @OutputTimeUnit(TimeUnit.MILLISECONDS) @BenchmarkMode(Mode.SingleShotTime) @Warmup(iterations = 5) @Measurement(iterations = 1) @State(Scope.Benchmark) @Fork(1) public class JmhDemoThree { public static void main(String[] args) throws Exception{ Options options = new OptionsBuilder() .include(JmhDemoThree.class.getName()) .build(); new Runner(options).run(); } /** * 序列化次數 */ @Param({"100", "10000", "1000000"}) private int number; private Userinfo userinfo; private String fastjson_jsonStr; private String gson_jsonStr; private String jackson_jsonStr; /** * fastjson bean2Json */ @Benchmark public void fastjson_bean2Json(){ for (int i=0;i<number;i++){ JsonUtil.fastjson_bean2Json(userinfo); } } /** * gson bean2Json */ @Benchmark public void gson_bean2Json(){ for (int i=0;i<number;i++){ JsonUtil.gson_bean2Json(userinfo); } } /** * jackson bean2Json */ @Benchmark public void jackson_bean2Json(){ for (int i=0;i<number;i++){ JsonUtil.jackson_bean2Json(userinfo); } } /** * fastjson json2Bean */ @Benchmark public void fastjson_json2Bean(){ for (int i=0;i<number;i++){ JsonUtil.fastjson_json2Bean(fastjson_jsonStr,Userinfo.class); } } /** * gson json2Bean */ @Benchmark public void gson_json2Bean(){ for (int i=0;i<number;i++){ JsonUtil.gson_json2Bean(gson_jsonStr,Userinfo.class); } } /** * jackson json2Bean */ @Benchmark public void jackson_json2Bean(){ for (int i=0;i<number;i++){ JsonUtil.jackson_json2Bean(jackson_jsonStr,Userinfo.class); } } /** * 初始化參數 */ @Setup public void init(){ userinfo = new Userinfo(); userinfo.setUsername("張三"); userinfo.setGender("男"); userinfo.setAge(18); userinfo.setBirthday(new Date()); userinfo.setCreateTime(System.currentTimeMillis()); List<String> list = new ArrayList<>(); list.add("北京三裡屯兒那條街那條巷那一號"); list.add("上海三裡屯兒那條街那條巷那一號"); list.add("深圳三裡屯兒那條街那條巷那一號"); userinfo.setAddress(list); fastjson_jsonStr = JsonUtil.fastjson_bean2Json(userinfo); gson_jsonStr = JsonUtil.gson_bean2Json(userinfo); jackson_jsonStr = JsonUtil.jackson_bean2Json(userinfo); } }
(其它相關代碼後附)
測試結果:
//—省略測試過程結果———-
Benchmark (number) Mode Cnt Score Error Units
JmhDemoThree.fastjson_bean2Json 100 ss 1.586 ms/op
JmhDemoThree.fastjson_bean2Json 10000 ss 3.683 ms/op
JmhDemoThree.fastjson_bean2Json 1000000 ss 500.924 ms/op
JmhDemoThree.fastjson_json2Bean 100 ss 0.978 ms/op
JmhDemoThree.fastjson_json2Bean 10000 ss 5.493 ms/op
JmhDemoThree.fastjson_json2Bean 1000000 ss 362.337 ms/op
JmhDemoThree.gson_bean2Json 100 ss 2.106 ms/op
JmhDemoThree.gson_bean2Json 10000 ss 28.693 ms/op
JmhDemoThree.gson_bean2Json 1000000 ss 1890.999 ms/op
JmhDemoThree.gson_json2Bean 100 ss 7.175 ms/op
JmhDemoThree.gson_json2Bean 10000 ss 110.298 ms/op
JmhDemoThree.gson_json2Bean 1000000 ss 7310.555 ms/op
JmhDemoThree.jackson_bean2Json 100 ss 2.111 ms/op
JmhDemoThree.jackson_bean2Json 10000 ss 8.859 ms/op
JmhDemoThree.jackson_bean2Json 1000000 ss 376.587 ms/op
JmhDemoThree.jackson_json2Bean 100 ss 1.992 ms/op
JmhDemoThree.jackson_json2Bean 10000 ss 10.723 ms/op
JmhDemoThree.jackson_json2Bean 1000000 ss 714.569 ms/op
從測試結果可以看出,不論是bean2Json還是json2Bean,fastjson的性能比gson、jackson都要好一些,當然,jackson性能也很不錯(不愧是spring默認的序列化和反序列化工具),尤其是當序列化與反序列化次數較多時,fastjson優勢尤其明顯。當然,由於筆者用於測試的實體bean數據結構還是較為簡單,在一些較為復雜的數據結構場景下,其各自的性能表現可能有所不一樣。(筆者用的測試Mode是Mode.SingleShotTime,隻測試一次,且由於機器等原因,所以誤差可能相對較大。有興趣的讀者,可以測試一下不同測試Mode下,更復雜的數據結構場景下,各序列化/反序列化工具的性能表現)
四、小結
1、JMH官方並沒有提供比較詳細的使用文檔(這也是筆者整理本文的重要原因),但是其提供瞭許多詳細、較容易理解的例子,有問題的可以參考,地址為:http://hg.openjdk.java.net/code-tools/jmh/file/99d7b73cf1e3/jmh-samples/src/main/java/org/openjdk/jmh/samples 。
2、JMH中的參數配置,許多參數可以直接在main方法的options中設置,也可以通過在類上直接添加註解配置。
3、註意:跑測試的時候要直接用run的方式跑,不要用debug的方式跑,否則會出錯。
4、JMH適用於方法級別的基準性能測試,並不適用於跨系統、跨服務之間的全鏈路測試。
5、使用JMH基準測試,雖然精度可以達到微妙級,但是測試結果依然是會存在一定誤差的;由於測試機器、場景、jvm配置等不同而引起測試誤差是完全可能的,隻是這個誤差能否在可接受的范圍內。
6、最終測試結果是fork參數與每次測試迭代參數的合集,如fork值為3,iterations值為5,那最終測試次數就是 3 * 5 = 15次。
參考文章:
http://hg.openjdk.java.net/code-tools/jmh/file/99d7b73cf1e3/jmh-samples/src/main/java/org/openjdk/jmh/samples
http://java-performance.info/jmh/
https://www.cnblogs.com/tranquillity/p/9488572.html
https://www.xncoding.com/2018/01/07/java/jmh.html
https://blog.csdn.net/lxbjkben/article/details/79410740
http://blog.dyngr.com/blog/2016/10/29/introduction-of-jmh/
http://irfen.me/java-jmh-simple-microbenchmark/
https://www.cnblogs.com/bestzhang/p/10082119.html
附:
json工具pom依賴:
<!--fastJson--> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.58</version> </dependency> <!--gson--> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.5</version> </dependency> <!--jackson--> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.9</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.9.9</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.9.9</version> </dependency>
Userinfo.java:
package com.xiaojiang; import java.util.Date; import java.util.List; /** * @ Description:用戶信息 * @ Author :xiaojiang * @ Date :Created in 2019-06-19 * @ Version :0.0.1 */ public class Userinfo { private String username; //用戶名 private String gender; //用戶性別 private Integer age; //用戶年齡 private Date birthday; //用戶生日 private List<String> address; // 用戶地址 private Long createTime; //用戶創建時間 public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public List<String> getAddress() { return address; } public void setAddress(List<String> address) { this.address = address; } public Long getCreateTime() { return createTime; } public void setCreateTime(Long createTime) { this.createTime = createTime; } @Override public String toString() { return "Userinfo{" + "username='" + username + '\'' + ", gender='" + gender + '\'' + ", age=" + age + ", birthday=" + birthday + ", address=" + address + ", createTime=" + createTime + '}'; } }
JsonUtil.java:
package com.xiaojiang; import com.alibaba.fastjson.JSON; import com.fasterxml.jackson.core.JsonProcessingException; import java.io.IOException; /** * @ Description:json工具類 * @ Author :xiaojiang * @ Date :Created in 2019-06-19 * @ Version :0.0.1 */ public class JsonUtil { private static com.google.gson.Gson gson = new com.google.gson.GsonBuilder().create(); private static com.fasterxml.jackson.databind.ObjectMapper jacksonMapper = new com.fasterxml.jackson.databind.ObjectMapper(); public static String fastjson_bean2Json(Object object){ return com.alibaba.fastjson.JSON.toJSONString(object); } public static <T> T fastjson_json2Bean(String jsonStr, Class<T> objectClass) { return JSON.parseObject(jsonStr, objectClass); } public static String gson_bean2Json(Object object){ return gson.toJson(object); } public static <T> T gson_json2Bean(String jsonStr, Class<T> objectClass){ return gson.fromJson(jsonStr,objectClass); } public static String jackson_bean2Json(Object object) { try { return jacksonMapper.writeValueAsString(object); } catch (JsonProcessingException e) { e.printStackTrace(); } return null; } public static <T> T jackson_json2Bean(String jsonStr, Class<T> objectClass){ try { return jacksonMapper.readValue(jsonStr,objectClass); } catch (IOException e) { e.printStackTrace(); } return null; } }
到此這篇關於詳解Java使用JMH進行基準性能測試的文章就介紹到這瞭,更多相關Java 基準性能測試內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- java比較兩個json文件的差異及說明
- 詳解Java編譯優化之循環展開和粗化鎖
- java中HashMap的7種遍歷方式與性能分析
- JSON反序列化Long變Integer或Double的問題及解決
- 淺談HashMap中7種遍歷方式的性能分析