一、案例二代碼
這次我們來搞一下官網(wǎng)文檔的第二個(gè)案例,我刪除了一些沒用的注釋,然后對(duì)代碼做了一下注釋的翻譯,可以看一下意思。
package com.levi;
import org.openjdk.jmh.annotations.*;
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;
// 預(yù)熱注解,修改為只預(yù)熱一輪,每輪只跑一秒,默認(rèn)是5,5這里改為1,1
@Warmup(iterations = 1,time = 1)
// 測試執(zhí)行注解,修改為只執(zhí)行一輪,每輪只跑一秒,默認(rèn)是5,5這里改為1,1
@Measurement(iterations = 1,time = 1)
public class JMHSample_02_01_BenchmarkModes {
/*
* Mode.Throughput, as stated in its Javadoc, measures the raw throughput by
* continuously calling the benchmark method in a time-bound iteration, and
* counting how many times we executed the method.
*
* We are using the special annotation to select the units to measure in,
* although you can use the default.
*
* AI直譯:Mode.Throughput,如其Javadoc所述,通過在時(shí)間限制的迭代中連續(xù)調(diào)用基準(zhǔn)方法,
* 并計(jì)算我們執(zhí)行該方法的次數(shù)來衡量原始吞吐量。我們正在使用特殊注解來選擇要測量的單位,盡管你可以使用默認(rèn)值。
*
* 我根據(jù)我的理解還是說幾句人話吧,他的意思是我們之前不是在案例1中輸出的是吞吐量的測試指標(biāo)嗎,這里的意思是你可以
* 使用@BenchmarkMode這個(gè)注解,里面設(shè)置參數(shù)Mode.Throughput一樣可以是通過吞吐量的指標(biāo)的,或者說你不設(shè)置,默認(rèn)
* 本身就是吞吐量,我們第一個(gè)案例就是默認(rèn)的。
* 所以我們在第一個(gè)方法上看到新出現(xiàn)的兩個(gè)注解
* @BenchmarkMode:設(shè)置計(jì)算指標(biāo)
* @OutputTimeUnit:計(jì)算模式對(duì)應(yīng)的單位
*/
@Benchmark
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.SECONDS)
public void measureThroughput() throws InterruptedException {
TimeUnit.MILLISECONDS.sleep(100);
}
/*
* Mode.AverageTime measures the average execution time, and it does it
* in the way similar to Mode.Throughput.
* 在性能測試或基準(zhǔn)測試的背景下,Mode.AverageTime(平均時(shí)間模式)測量了給定操作或代碼片段的平均執(zhí)行時(shí)間。
* 該模式計(jì)算了每次調(diào)用被測試代碼所花費(fèi)的平均時(shí)間。它與Mode.Throughput(吞吐量模式)相似,兩種模式都專注于性能測量,
* 但它們在優(yōu)先考慮的性能方面存在差異。以下是Mode.AverageTime和Mode.Throughput之間的簡要比較:
* 平均時(shí)間:該模式計(jì)算每個(gè)操作或調(diào)用的平均執(zhí)行時(shí)間。它提供了關(guān)于單個(gè)操作平均執(zhí)行時(shí)間的信息。
* 吞吐量:另一方面,Mode.Throughput關(guān)注的是在給定時(shí)間內(nèi)完成的操作速率。它衡量每單位時(shí)間內(nèi)可以執(zhí)行多少操作,通常是每秒。
* 它提供了系統(tǒng)在高負(fù)載下處理大量操作的效率信息。
* 雖然兩種模式都提供了有關(guān)性能的有價(jià)值的信息,但它們服務(wù)于不同的目的,可能適用于不同類型的性能分析。
* Mode.AverageTime適用于了解單個(gè)操作的平均延遲或執(zhí)行時(shí)間,而Mode.Throughput更適用于在指定時(shí)間范圍內(nèi)最大化完成的操作數(shù)量。
*
*
* Some might say it is the reciprocal throughput, and it really is.
* There are workloads where measuring times is more convenient though.
* 有人說,這個(gè)指標(biāo)是吞吐量的倒數(shù),你也可以這么理解,不過有時(shí)候你測試的時(shí)候,統(tǒng)計(jì)時(shí)間維度是更加直觀的。
*
* 換言之,這個(gè)是統(tǒng)計(jì)你方法的執(zhí)行平均時(shí)間的,所以看起來比吞吐量更加直觀,畢竟耗時(shí)是我們普遍關(guān)心的第一指標(biāo)
*/
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public void measureAvgTime() throws InterruptedException {
TimeUnit.MILLISECONDS.sleep(100);
}
/*
* Mode.SampleTime samples the execution time. With this mode, we are
* still running the method in a time-bound iteration, but instead of
* measuring the total time, we measure the time spent in *some* of
* the benchmark method calls.
*
* Mode.SampleTime是用于對(duì)方法執(zhí)行時(shí)間進(jìn)行采樣的一種模式。在這種模式下,我們?nèi)匀辉谝粋€(gè)有時(shí)間限制的迭代中運(yùn)行方法,
* 但不再測量總時(shí)間,而是測量一部分基準(zhǔn)方法調(diào)用所花費(fèi)的時(shí)間。使用Mode.SampleTime模式時(shí),
* 基準(zhǔn)測試框架會(huì)定期中斷方法的執(zhí)行并記錄經(jīng)過的時(shí)間。通過只對(duì)部分調(diào)用進(jìn)行采樣,可以減少與連續(xù)時(shí)間測量相關(guān)的開銷,
* 同時(shí)仍能提供有關(guān)方法執(zhí)行時(shí)間分布的有意義數(shù)據(jù),而不僅僅關(guān)注整體持續(xù)時(shí)間。這種模式對(duì)于識(shí)別執(zhí)行時(shí)間的變化非常有用,
* 特別是如果方法的某些部分可能具有不同的性能特點(diǎn)或表現(xiàn)出間歇性行為。它使開發(fā)人員能夠了解方法在不同條件下的性能表現(xiàn),
* 并幫助優(yōu)化其性能。
*
* This allows us to infer the distributions, percentiles, etc.
* JMH also tries to auto-adjust sampling frequency: if the method
* is long enough, you will end up capturing all the samples.
* 這樣可以讓我們推斷出分布情況、百分位數(shù)等。JMH 還會(huì)嘗試自動(dòng)調(diào)整采樣頻率:如果方法足夠長,你最終會(huì)捕獲到所有的樣本
*
* 這個(gè)解釋的不明確,我們待會(huì)通過現(xiàn)象來看一下具體啥意思。
*/
@Benchmark
@BenchmarkMode(Mode.SampleTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public void measureSamples() throws InterruptedException {
TimeUnit.MILLISECONDS.sleep(100);
}
/*
* Mode.SingleShotTime measures the single method invocation time. As the Javadoc
* suggests, we do only the single benchmark method invocation. The iteration
* time is meaningless in this mode: as soon as benchmark method stops, the
* iteration is over.
*
* Mode.SingleShotTime測量的是單個(gè)方法調(diào)用的時(shí)間。正如Javadoc所建議的,我們只進(jìn)行一次基準(zhǔn)方法的調(diào)用。
* 在這種模式下,迭代時(shí)間是沒有意義的:一旦基準(zhǔn)方法停止,迭代就結(jié)束了。
*
* This mode is useful to do cold startup tests, when you specifically
* do not want to call the benchmark method continuously.
* 這種模式在進(jìn)行冷啟動(dòng)測試時(shí)非常有用,當(dāng)你不想連續(xù)調(diào)用基準(zhǔn)方法時(shí)。
*
* 說白了就是只測試一次,就跟你跑main函數(shù)一樣的,沒有預(yù)熱,就是冷啟動(dòng)的測試。
*/
@Benchmark
@BenchmarkMode(Mode.SingleShotTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public void measureSingleShot() throws InterruptedException {
TimeUnit.MILLISECONDS.sleep(100);
}
/*
* We can also ask for multiple benchmark modes at once. All the tests
* above can be replaced with just a single test like this:
*
* 這個(gè)注解還能寫數(shù)組,指定多種測試指標(biāo),一起生效
*/
@Benchmark
@BenchmarkMode({Mode.Throughput, Mode.AverageTime, Mode.SampleTime, Mode.SingleShotTime})
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public void measureMultiple() throws InterruptedException {
TimeUnit.MILLISECONDS.sleep(100);
}
/*
* Or even...
* 如果你懶得寫很多模式,你還能直接用Mode.All來表示全部的模式
*/
@Benchmark
@BenchmarkMode(Mode.All)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public void measureAll() throws InterruptedException {
TimeUnit.MILLISECONDS.sleep(100);
}
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.include(JMHSample_02_01_BenchmarkModes.class.getSimpleName())
.forks(1)
.build();
new Runner(opt).run();
}
}
二、@BenchmarkMode
我們先不急著運(yùn)行程序,我們在看完上面的例子之后可以看到這次出現(xiàn)了一個(gè)新的注解,就是
@BenchmarkMode
@Inherited
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface BenchmarkMode {
Mode[] value();
}
這個(gè)注解我們看到,作用的位置就是方法和類上面,你要是標(biāo)注在類上,那就這個(gè)類所有的方法都按照這個(gè)配置生效了。
而且我們注意到他有一個(gè)變量,是Mode類型的數(shù)組,注意是數(shù)組,也就是可以傳入多個(gè)。我們看一下這個(gè)Mode類型是啥。
public enum Mode {
Throughput("thrpt", "Throughput, ops/time"),
AverageTime("avgt", "Average time, time/op"),
SampleTime("sample", "Sampling time"),
SingleShotTime("ss", "Single shot invocation time"),
All("all", "All benchmark modes");
}
就是個(gè)枚舉類型,總共五個(gè)類型,我們上面的注釋其實(shí)也標(biāo)注了這五個(gè)類型的各自的作用。
三、 @OutputTimeUnit
與@BenchmarkMode 配套的還有一個(gè)注解就是@OutputTimeUnit。
@Inherited
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface OutputTimeUnit {
TimeUnit value();
}
他的作用就是你輸出指標(biāo)的時(shí)間單位,沒別的了。OK,我們在大致有個(gè)了解之后,我們開始通過執(zhí)行程序來看一下結(jié)果,加深我們對(duì)于注解的理解。
四、執(zhí)行程序
鑒于我們這里這次一次寫了N個(gè)方法測試,輸出的報(bào)告巨長,我們這里就一個(gè)一個(gè)的測試,這樣方便觀察。
1、測試吞吐模式:measureThroughput
package com.levi;
import org.openjdk.jmh.annotations.*;
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;
// 預(yù)熱注解,修改為只預(yù)熱一輪,每輪只跑一秒,默認(rèn)是5,5這里改為1,1
@Warmup(iterations = 1,time = 1)
// 測試執(zhí)行注解,修改為只執(zhí)行一輪,每輪只跑一秒,默認(rèn)是5,5這里改為1,1
@Measurement(iterations = 1,time = 1)
public class JMHSample_02_01_BenchmarkModes {
/*
* Mode.Throughput, as stated in its Javadoc, measures the raw throughput by
* continuously calling the benchmark method in a time-bound iteration, and
* counting how many times we executed the method.
*
* We are using the special annotation to select the units to measure in,
* although you can use the default.
*
* AI直譯:Mode.Throughput,如其Javadoc所述,通過在時(shí)間限制的迭代中連續(xù)調(diào)用基準(zhǔn)方法,
* 并計(jì)算我們執(zhí)行該方法的次數(shù)來衡量原始吞吐量。我們正在使用特殊注解來選擇要測量的單位,盡管你可以使用默認(rèn)值。
*
* 我根據(jù)我的理解還是說幾句人話吧,他的意思是我們之前不是在案例1中輸出的是吞吐量的測試指標(biāo)嗎,這里的意思是你可以
* 使用@BenchmarkMode這個(gè)注解,里面設(shè)置參數(shù)Mode.Throughput一樣可以是通過吞吐量的指標(biāo)的,或者說你不設(shè)置,默認(rèn)
* 本身就是吞吐量,我們第一個(gè)案例就是默認(rèn)的。
* 所以我們在第一個(gè)方法上看到新出現(xiàn)的兩個(gè)注解
* @BenchmarkMode:設(shè)置計(jì)算指標(biāo)
* @OutputTimeUnit:計(jì)算模式對(duì)應(yīng)的單位
*/
@Benchmark
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.SECONDS)
public void measureThroughput() throws InterruptedException {
TimeUnit.MILLISECONDS.sleep(100);
}
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.include(JMHSample_02_01_BenchmarkModes.class.getSimpleName())
.forks(1)
.build();
new Runner(opt).run();
}
}
運(yùn)行結(jié)果為:
Benchmark :JMHSample_02_01_BenchmarkModes.measureThroughput
Mode :thrpt
Cnt : 因?yàn)槲铱刂屏?次,所以這里沒東西
Score :9.160 這個(gè)分?jǐn)?shù)在吞吐這里其實(shí)就是你執(zhí)行的吞吐量,因?yàn)槲覍懙腀OutputTimeUnit(TimeUnit.SECONDS)單位是秒,所以意思就是一秒能執(zhí)行9.16次。
Error :沒輸出
Units:ops/s
我們看到這個(gè)吞吐量其實(shí)和我們在第一個(gè)案例測試的差不多,其實(shí)他就是默認(rèn)的。你不寫就是他。
2、測試平均時(shí)間模式:measureAvgTime
package com.levi;
import org.openjdk.jmh.annotations.*;
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;
// 預(yù)熱注解,修改為只預(yù)熱一輪,每輪只跑一秒,默認(rèn)是5,5這里改為1,1
@Warmup(iterations = 1,time = 1)
// 測試執(zhí)行注解,修改為只執(zhí)行一輪,每輪只跑一秒,默認(rèn)是5,5這里改為1,1
@Measurement(iterations = 1,time = 1)
public class JMHSample_02_01_BenchmarkModes {
/*
* Mode.AverageTime measures the average execution time, and it does it
* in the way similar to Mode.Throughput.
* 在性能測試或基準(zhǔn)測試的背景下,Mode.AverageTime(平均時(shí)間模式)測量了給定操作或代碼片段的平均執(zhí)行時(shí)間。
* 該模式計(jì)算了每次調(diào)用被測試代碼所花費(fèi)的平均時(shí)間。它與Mode.Throughput(吞吐量模式)相似,兩種模式都專注于性能測量,
* 但它們在優(yōu)先考慮的性能方面存在差異。以下是Mode.AverageTime和Mode.Throughput之間的簡要比較:
* 平均時(shí)間:該模式計(jì)算每個(gè)操作或調(diào)用的平均執(zhí)行時(shí)間。它提供了關(guān)于單個(gè)操作平均執(zhí)行時(shí)間的信息。
* 吞吐量:另一方面,Mode.Throughput關(guān)注的是在給定時(shí)間內(nèi)完成的操作速率。它衡量每單位時(shí)間內(nèi)可以執(zhí)行多少操作,通常是每秒。
* 它提供了系統(tǒng)在高負(fù)載下處理大量操作的效率信息。
* 雖然兩種模式都提供了有關(guān)性能的有價(jià)值的信息,但它們服務(wù)于不同的目的,可能適用于不同類型的性能分析。
* Mode.AverageTime適用于了解單個(gè)操作的平均延遲或執(zhí)行時(shí)間,而Mode.Throughput更適用于在指定時(shí)間范圍內(nèi)最大化完成的操作數(shù)量。
*
*
* Some might say it is the reciprocal throughput, and it really is.
* There are workloads where measuring times is more convenient though.
* 有人說,這個(gè)指標(biāo)是吞吐量的倒數(shù),你也可以這么理解,不過有時(shí)候你測試的時(shí)候,統(tǒng)計(jì)時(shí)間維度是更加直觀的。
*
* 換言之,這個(gè)是統(tǒng)計(jì)你方法的執(zhí)行平均時(shí)間的,所以看起來比吞吐量更加直觀,畢竟耗時(shí)是我們普遍關(guān)心的第一指標(biāo)
*/
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public void measureAvgTime() throws InterruptedException {
TimeUnit.MILLISECONDS.sleep(100);
}
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.include(JMHSample_02_01_BenchmarkModes.class.getSimpleName())
.forks(1)
.build();
new Runner(opt).run();
}
}
運(yùn)行結(jié)果如下:
Benchmark :JMHSample_02_01_BenchmarkModes.measureAvgTime
Mode:avgt 平均統(tǒng)計(jì)模式
Cnt :同上
Score:108407.350
Error :沒錯(cuò)誤,不輸出
Units:us/op 其實(shí)你能看出來,他是時(shí)間除以執(zhí)行次數(shù),所以就是吞吐量的倒數(shù),吞吐量的意思是每秒能執(zhí)行幾次,這里就是執(zhí)行一次需要幾秒,不就是平均時(shí)間嗎。只是我指定的時(shí)間單位是@OutputTimeUnit(TimeUnit.MICROSECONDS)微秒,所以這里自然也就是這個(gè)單位。
他主打的是一個(gè)平均耗時(shí)。
3、測試統(tǒng)計(jì)時(shí)間:measureSamples
package com.levi;
import org.openjdk.jmh.annotations.*;
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;
// 預(yù)熱注解,修改為只預(yù)熱一輪,每輪只跑一秒,默認(rèn)是5,5這里改為1,1
@Warmup(iterations = 1,time = 1)
// 測試執(zhí)行注解,修改為只執(zhí)行一輪,每輪只跑一秒,默認(rèn)是5,5這里改為1,1
@Measurement(iterations = 1,time = 1)
public class JMHSample_02_01_BenchmarkModes {
/*
* Mode.SampleTime samples the execution time. With this mode, we are
* still running the method in a time-bound iteration, but instead of
* measuring the total time, we measure the time spent in *some* of
* the benchmark method calls.
*
* Mode.SampleTime是用于對(duì)方法執(zhí)行時(shí)間進(jìn)行采樣的一種模式。在這種模式下,我們?nèi)匀辉谝粋€(gè)有時(shí)間限制的迭代中運(yùn)行方法,
* 但不再測量總時(shí)間,而是測量一部分基準(zhǔn)方法調(diào)用所花費(fèi)的時(shí)間。使用Mode.SampleTime模式時(shí),
* 基準(zhǔn)測試框架會(huì)定期中斷方法的執(zhí)行并記錄經(jīng)過的時(shí)間。通過只對(duì)部分調(diào)用進(jìn)行采樣,可以減少與連續(xù)時(shí)間測量相關(guān)的開銷,
* 同時(shí)仍能提供有關(guān)方法執(zhí)行時(shí)間分布的有意義數(shù)據(jù),而不僅僅關(guān)注整體持續(xù)時(shí)間。這種模式對(duì)于識(shí)別執(zhí)行時(shí)間的變化非常有用,
* 特別是如果方法的某些部分可能具有不同的性能特點(diǎn)或表現(xiàn)出間歇性行為。它使開發(fā)人員能夠了解方法在不同條件下的性能表現(xiàn),
* 并幫助優(yōu)化其性能。
*
* This allows us to infer the distributions, percentiles, etc.
* JMH also tries to auto-adjust sampling frequency: if the method
* is long enough, you will end up capturing all the samples.
* 這樣可以讓我們推斷出分布情況、百分位數(shù)等。JMH 還會(huì)嘗試自動(dòng)調(diào)整采樣頻率:如果方法足夠長,你最終會(huì)捕獲到所有的樣本
*
* 這個(gè)解釋的不明確,我們待會(huì)通過現(xiàn)象來看一下具體啥意思。
*/
@Benchmark
@BenchmarkMode(Mode.SampleTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public void measureSamples() throws InterruptedException {
TimeUnit.MILLISECONDS.sleep(100);
}
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.include(JMHSample_02_01_BenchmarkModes.class.getSimpleName())
.forks(1)
.build();
new Runner(opt).run();
}
}
他是以一種分布統(tǒng)計(jì)的方式輸出的測試指標(biāo),單位還是平均時(shí)間耗時(shí),等于說百分之99的測試跑一次是109707.264us的耗時(shí),他內(nèi)部給你做了一個(gè)測試,拆分出來測的,測出這么個(gè)結(jié)果來。
能看出來一個(gè)波動(dòng),和你實(shí)現(xiàn)的代碼穩(wěn)定性,而且他是抽樣測試,不會(huì)都給你統(tǒng)計(jì),比如我們設(shè)置的跑1輪,每輪一秒??赡苓@一秒跑了一萬次,他不會(huì)像吞吐和平均那個(gè)樣都算進(jìn)去,他是一個(gè)抽樣,可能抽了前面后面,沒取中間??赡軌焊褪浅榱饲懊?。是一個(gè)分布統(tǒng)計(jì)。
4、測試只跑一次:measureSingleShot
package com.levi;
import org.openjdk.jmh.annotations.*;
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;
// 預(yù)熱注解,修改為只預(yù)熱一輪,每輪只跑一秒,默認(rèn)是5,5這里改為1,1
@Warmup(iterations = 1,time = 1)
// 測試執(zhí)行注解,修改為只執(zhí)行一輪,每輪只跑一秒,默認(rèn)是5,5這里改為1,1
@Measurement(iterations = 1,time = 1)
public class JMHSample_02_01_BenchmarkModes {
/*
* Mode.SingleShotTime measures the single method invocation time. As the Javadoc
* suggests, we do only the single benchmark method invocation. The iteration
* time is meaningless in this mode: as soon as benchmark method stops, the
* iteration is over.
*
* Mode.SingleShotTime測量的是單個(gè)方法調(diào)用的時(shí)間。正如Javadoc所建議的,我們只進(jìn)行一次基準(zhǔn)方法的調(diào)用。
* 在這種模式下,迭代時(shí)間是沒有意義的:一旦基準(zhǔn)方法停止,迭代就結(jié)束了。
*
* This mode is useful to do cold startup tests, when you specifically
* do not want to call the benchmark method continuously.
* 這種模式在進(jìn)行冷啟動(dòng)測試時(shí)非常有用,當(dāng)你不想連續(xù)調(diào)用基準(zhǔn)方法時(shí)。
*
* 說白了就是只測試一次,就跟你跑main函數(shù)一樣的,沒有預(yù)熱,就是冷啟動(dòng)的測試。
*/
@Benchmark
@BenchmarkMode(Mode.SingleShotTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public void measureSingleShot() throws InterruptedException {
TimeUnit.MILLISECONDS.sleep(100);
}
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.include(JMHSample_02_01_BenchmarkModes.class.getSimpleName())
.forks(1)
.build();
new Runner(opt).run();
}
}
執(zhí)行結(jié)果如下:
這就是測試?yán)鋯?dòng)的,沒預(yù)熱,就是直接跑,你也能看到單位是us/op。還是執(zhí)行一次要多久。還是個(gè)平均值,只不過就是沒預(yù)熱直接開跑的。就跑一次。
5、測試多種模式組合:measureMultiple
package com.levi;
import org.openjdk.jmh.annotations.*;
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;
// 預(yù)熱注解,修改為只預(yù)熱一輪,每輪只跑一秒,默認(rèn)是5,5這里改為1,1
@Warmup(iterations = 1,time = 1)
// 測試執(zhí)行注解,修改為只執(zhí)行一輪,每輪只跑一秒,默認(rèn)是5,5這里改為1,1
@Measurement(iterations = 1,time = 1)
public class JMHSample_02_01_BenchmarkModes {
/*
* We can also ask for multiple benchmark modes at once. All the tests
* above can be replaced with just a single test like this:
*
* 這個(gè)注解還能寫數(shù)組,指定多種測試指標(biāo),一起生效
*/
@Benchmark
@BenchmarkMode({Mode.Throughput, Mode.AverageTime, Mode.SampleTime, Mode.SingleShotTime})
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public void measureMultiple() throws InterruptedException {
TimeUnit.MILLISECONDS.sleep(100);
}
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.include(JMHSample_02_01_BenchmarkModes.class.getSimpleName())
.forks(1)
.build();
new Runner(opt).run();
}
}
因?yàn)槲覀兦懊婵戳薓ode是一個(gè)數(shù)組,所以可以傳入多個(gè)模式。結(jié)果就是一起統(tǒng)計(jì)輸出了。
6、測試全量模式:measureAll
package com.levi;
import org.openjdk.jmh.annotations.*;
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;
// 預(yù)熱注解,修改為只預(yù)熱一輪,每輪只跑一秒,默認(rèn)是5,5這里改為1,1
@Warmup(iterations = 1,time = 1)
// 測試執(zhí)行注解,修改為只執(zhí)行一輪,每輪只跑一秒,默認(rèn)是5,5這里改為1,1
@Measurement(iterations = 1,time = 1)
public class JMHSample_02_01_BenchmarkModes {
/*
* Or even...
* 如果你懶得寫很多模式,你還能直接用Mode.All來表示全部的模式
*/
@Benchmark
@BenchmarkMode(Mode.All)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public void measureAll() throws InterruptedException {
TimeUnit.MILLISECONDS.sleep(100);
}
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.include(JMHSample_02_01_BenchmarkModes.class.getSimpleName())
.forks(1)
.build();
new Runner(opt).run();
}
}
自然就是全部的統(tǒng)計(jì)都輸出了:和上面一樣。
你也可以看他的單位就知道他輸出的計(jì)算方式了,次數(shù)除以時(shí)間,那就是平均時(shí)間的執(zhí)行次數(shù),就是吞吐。
時(shí)間除以次數(shù),就是統(tǒng)計(jì)的某種模式下的平均時(shí)間。
五、總結(jié)
沒啥總結(jié)的就是那兩個(gè)注解,很詳細(xì)了。文章來源:http://www.zghlxwxcb.cn/news/detail-852948.html
六、參考鏈接
1、JMH官方文檔文章來源地址http://www.zghlxwxcb.cn/news/detail-852948.html
到了這里,關(guān)于橘子學(xué)JDK之JMH-02(BenchmarkModes)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!