In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-04-09 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article mainly introduces "what are the advantages of performance tuning essential sharp weapon JMH". In daily operation, I believe that many people have doubts about the advantages of performance tuning necessary sharp weapon JMH. The editor consulted all kinds of materials and sorted out simple and easy-to-use operation methods. I hope it will be helpful for everyone to answer the doubts about "what are the advantages of performance tuning necessary sharp weapon JMH?" Next, please follow the editor to study!
Introduction to JMH
JMH (Java Microbenchmark Harness) is a suite of tools for code microbenchmarking, which is mainly based on the method-level benchmark, and the accuracy can reach nanosecond. The tool was written by bulls who implement JIT within Oracle, and they should know better than anyone about JIT and the impact of JVM on benchmarking.
When you locate a hot method and want to further optimize the performance of the method, you can use JMH to quantitatively analyze the optimization results.
Typical application scenarios of JMH are as follows:
Want to know exactly how long a method needs to be executed and the correlation between execution time and input
Compare the throughput of different implementations of interfaces under given conditions
See what percentage of requests are completed and how long it takes
Let's take two methods of string concatenation as examples and use JMH as a benchmark.
Add dependency
Because JMH comes with JDK9, if it is a previous version of JDK9, you need to add the following dependencies (currently, the latest version of JMH is 1.23):
Org.openjdk.jmh jmh-core 1.23 org.openjdk.jmh jmh-generator-annprocess 1.23
Write benchmark tests
Next, create a JMH test class to determine which string concatenation takes less time between + and StringBuilder.append (), as shown in the following code:
@ 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/
Perform benchmark tests
After the preparatory work is done, run the code, wait for a moment, and the test results will come out. Here is a brief description of the results:
# JMH version: 1.23 # VM version: JDK 1.8.02.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)
This part is the basic information of the test, such as the Java path used, the number of iterations of the preheating code, the number of iterations of the measurement code, the number of threads used, the statistical unit of the test, and so on.
# Warmup Iteration 1: 1083.569 ±(99.9%) 393.884 ns/op # Warmup Iteration 2: 864.685 ±(99.9%) 174.120 ns/op # Warmup Iteration 3: 798.310 ±(99.9%) 121.161 ns/op
This part is the performance index of each warm-up, and the preheating test will not be regarded as the final statistical result. The purpose of warm-up is to get JVM to optimize the code under test enough, for example, after warm-up, the code under test should be fully compiled and optimized by JIT.
Iteration 1: 810.667 ±(99.9) 51.505 ns/op Iteration 2: 807.861 ±(99.9) 13.163 ns/op Iteration 3: 851.421 ±(99.9) 33.564 ns/op Iteration 4: 805.675 ±(99.9) 33.038 ns/op Iteration 5: 821.020 ±(99.9) 66.943 ns/op Result "com.wupx.jmh.StringConnectTest.testStringBuilderAdd": 819.329 ±( 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 ±72.698 ns/op
This section shows the measurement iterations, each of which shows the current execution rate, that is, the time spent on an operation. After five iterations, statistics show that in this case, the average execution time of the testStringBuilderAdd method is 819.329 ns with a length of 100, with an error of 72.698 ns.
The final test results are as follows:
Benchmark (length) Mode Cnt Score Error Units StringConnectTest.testStringAdd 10 avgt 5 161.496 ±17.097 ns/op StringConnectTest.testStringAdd 50 avgt 5 1854.657 ±227.902 ns/op StringConnectTest.testStringAdd 100 avgt 5 6490.062 ±327.626 ns/op StringConnectTest.testStringBuilderAdd 10 avgt 5 68.769 ±4.460 Ns/op StringConnectTest.testStringBuilderAdd 50 avgt 5 413.021 ±30.950 ns/op StringConnectTest.testStringBuilderAdd 100 avgt 5 819.329 ±72.698 ns/op
The results show that the more concatenated characters, the better the performance of StringBuilder.append ().
Generate jar package execution
For some small tests, just write a main function in the above way and execute it manually.
For large-scale testing, it takes a long time to test and a large number of threads, coupled with the needs of the testing server, it is generally required to be executed in the Linux server.
JMH officially provides a way to generate jar packages for execution. We need to add a plugin to maven, as shown below:
Org.apache.maven.plugins maven-shade-plugin 2.4.1 package shade jmh-demo Org.openjdk.jmh.Main
Then execute the command of maven to generate the executable jar package and execute:
Mvn clean install java-jar target/jmh-demo.jar StringConnectTest
JMH Foundation
In order to make better use of the functions of JMH, the basic concepts of JMH are explained below:
@ BenchmarkMode
Used to configure the Mode option, which can be used on classes or methods. The value of this annotation is an array that can be executed together with several kinds of Mode, such as @ BenchmarkMode ({Mode.SampleTime, Mode.AverageTime}), or set to Mode.All, that is, to execute all of them.
Throughput: overall throughput, number of calls per second (in ops/time)
AverageTime: average time used, average time per operation, in time/op
SampleTime: random sampling, the final output of the distribution of sampling results
SingleShotTime: run it only once, and often set the number of Warmup to 0 at the same time, which is used to test the performance of cold start.
All: all the above modes are executed once
@ State
Through State, you can specify the scope of an object, and JMH instantiates and shares operations according to scope. @ State can be inherited and used, and if the parent class defines the annotation, the subclass does not need to be defined. Because JMH allows multiple threads to execute tests at the same time, the different options mean the following:
Scope.Benchmark: all test threads share an instance to test the performance of stateful instances under multi-thread sharing
Scope.Group: the same thread shares instances in the same group
Scope.Thread: default State, which assigns one instance to each test thread
@ OutputTimeUnit
Is the time unit of the statistical result and can be used for class or method annotations
@ Warmup
Some basic test parameters that need to be configured for preheating can be used on classes or methods. Generally speaking, the first few times of program testing will be relatively slow, so let the program carry out several rounds of preheating to ensure the accuracy of the test. The parameters are as follows:
Iterations: the number of times preheated
Time: time for each warm-up
TimeUnit: unit of time, default second
BatchSize: batch size, calling methods several times per operation
Why do you need to warm up?
Because of the existence of JVM's JIT mechanism, if a function is called many times, JVM will try to compile it into machine code to improve the execution speed, so it needs to be warmed up in order to make the benchmark result closer to the real situation.
@ Measurement
Some basic test parameters that need to be configured to actually call a method can be used on a class or method, and the parameters are the same as @ Warmup.
@ Threads
The test thread in each process can be used on a class or method.
@ Fork
The number of times to fork, which can be used on a class or method. If the number of fork is 2, JMH will fork two processes to test.
@ Param
A variety of situations in which a parameter is specified is especially suitable for testing the performance of a function under different parameter inputs. It can only be used on fields. To use this annotation, you must define the @ State annotation.
After introducing the commonly used annotations, let's take a look at the pitfalls of JMH.
JMH trap
When using JMH, be sure to avoid some pitfalls.
For example, dead code elimination in JIT optimization, such as the following code:
@ 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, then search for jmh and choose to install JMH plugin:
JMH plugin
This plug-in allows us to use JMH in the same way as JUnit. The main features are as follows:
Automatically generate methods with @ Benchmark
Like JUnit, run a separate Benchmark method
Run all Benchmark methods in the class
For example, you can right-click Generate..., to select action Generate JMH benchmark to generate a method with @ Benchmark.
Also, move the cursor to the method declaration and call the Run operation to run a separate Benchmark method.
Move the cursor to the line of the class name, right-click Run to run, and all methods annotated by @ Benchmark under the class will be executed.
JMH visualization
In addition, if you want to visualize the test results in graphical form, you can try these sites:
JMH Visual Chart: http://deepoove.com/jmh-visual-chart/
JMH Visualizer: https://jmh.morethan.io/
For example, if you import the json file of the above test example results, you can achieve visualization:
At this point, the study on "what are the advantages of JMH, a necessary tool for performance tuning," is over. I hope to be able to solve your doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.