基准测试工具JMH
junit用来测方法对不对 ab用来压测http服务
jhm是用测java方法性能的, 比如每秒能运行多少次,每次执行的耗时
jhm是写jdk的那些人整的
所以还是很可靠的
参考
官方介绍
https://openjdk.java.net/projects/code-tools/jmh/
官方示例代码– 点击左侧zip打包下载
https://hg.openjdk.java.net/code-tools/jmh/file/tip/jmh-samples/src/main/java/org/openjdk/jmh/samples/
工程创建
1
2
3
4
5
6
7
8
|
mvn archetype:generate \
-DinteractiveMode=false \
-DarchetypeGroupId=org.openjdk.jmh \
-DarchetypeArtifactId=jmh-java-benchmark-archetype \
-DarchetypeVersion=1.22 \
-DgroupId=fluffy.mo \
-DartifactId=test2 \
-Dversion=1.0
|
可以把java换成以下语言
1
2
3
4
|
jmh-java-benchmark-archetype
jmh-scala-benchmark-archetype
jmh-kotlin-benchmark-archetype
jmh-groovy-benchmark-archetype
|
修改pom.xml 增加以下属性
以整 jdk版本为11
1
2
3
4
5
6
|
<properties>
<javac.target>11</javac.target>
<java.version>11</java.version>
<maven.compiler.target>11</maven.compiler.target>
<maven.compiler.source>11</maven.compiler.source>
</properties>
|
测试字符串拼接效率
拼接字符串时, 五种方式的效率测试
StringBuilder、 StringBuffer、String-Concat、String-Format、直接相加
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
package fluffy.mo;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
import org.openjdk.jmh.runner.options.TimeValue;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class MyBenchmark {
@Benchmark
public void testStringBuffer(MyState st, Blackhole blackhole) {
var ss = new StringBuffer(prefix()).append(st.s1).append(st.s2).append(st.s3).append(st.s4).append(st.s5).toString();
blackhole.consume(ss);
}
@Benchmark
public void testStringBuilder(MyState st, Blackhole blackhole) {
var ss = new StringBuilder(prefix()).append(st.s1).append(st.s2).append(st.s3).append(st.s4).append(st.s5).toString();
blackhole.consume(ss);
}
@Benchmark
public void testStringConcat(MyState st, Blackhole blackhole) {
var ss = prefix().concat(st.s1).concat(st.s2).concat(st.s3).concat(st.s4).concat(st.s5);
blackhole.consume(ss);
}
@Benchmark
public void testStringAdd(MyState st, Blackhole blackhole) {
blackhole.consume(prefix() + st.s1 + st.s2 + st.s3 + st.s4 + st.s5);
}
@Benchmark
public void testStringFormat(MyState st, Blackhole blackhole) {
blackhole.consume(String.format("str-%s%s%s%s%s", st.s1, st.s2, st.s3, st.s4, st.s5));
}
private String prefix() {
return "str-";
}
@State(Scope.Thread)
public static class MyState {
public String s1, s2, s3, s4, s5;
@Setup
public void myInit() {
String ss = List.of(11, 22, 333, 4444, 55555).toString();
var arr = ss.split(",");
s1 = arr[0];
s2 = arr[1];
s3 = arr[2];
s4 = arr[3];
s5 = arr[4];
System.out.println("初始化状态");
}
}
public static void main(String[] args) throws Exception {
Options opt = new OptionsBuilder()
// 导入要测试的类 -- 正则匹配
.include(MyBenchmark.class.getSimpleName())
.mode(Mode.Throughput)
// 预热2轮 持续100毫秒--不计分数
.warmupIterations(3).warmupTime(TimeValue.microseconds(100))
// 测量8轮--统计分数
.measurementIterations(8).measurementTime(TimeValue.seconds(1))
.forks(1)
// 打印结果时使用的单位
.timeUnit(TimeUnit.MILLISECONDS)
.build();
new Runner(opt).run();
}
}
|
运行结果
1
2
3
4
5
6
|
Benchmark Mode Cnt Score Error Units
MyBenchmark.testStringAdd thrpt 8 15017.766 ± 2728.661 ops/ms
MyBenchmark.testStringBuffer thrpt 8 18837.796 ± 2774.093 ops/ms
MyBenchmark.testStringBuilder thrpt 8 18787.273 ± 2744.898 ops/ms
MyBenchmark.testStringConcat thrpt 8 8201.163 ± 1032.904 ops/ms
MyBenchmark.testStringFormat thrpt 8 540.847 ± 264.437 ops/ms
|
看起来 format 效果很差
避免jvm优化导致测试有误
举例
1
2
3
4
5
6
7
|
@Benchmark
public int case01() {
int x = 1;
int y = 2;
int sum = x + y;
return sum;
}
|
对于case01这段代码,可能会被jvm优化掉。
比如变成 return 3; 甚至调用case01()方法被替换成 3 。
换成这样
1
2
3
4
5
6
7
8
9
10
11
|
@State(Scope.Thread)
public static class MyState {
public int a = 1;
public int b = 2;
}
@Benchmark
public int case02(MyState state) {
int sum = state.a + state.b;
return sum;
}
|
参数对jvm不可预知,也就避免优化掉了,测试结果才会靠谱
文章作者
duansheli
上次更新
2019-12-25
(325c7b3)