本文目录导读:

我来提供一个简单实用的Java性能测试实操案例,使用JMH(Java Microbenchmark Harness)框架。
环境准备
Maven项目配置
<dependencies>
<!-- JMH核心库 -->
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>1.35</version>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>1.35</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
实战案例:字符串拼接性能测试
创建性能测试类
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;
@BenchmarkMode(Mode.Throughput) // 测试吞吐量
@OutputTimeUnit(TimeUnit.SECONDS) // 结果单位
@State(Scope.Thread) // 每个线程独立状态
public class StringConcatBenchmark {
private String baseString = "Hello";
private int count = 1000;
// 测试1: 使用+号拼接
@Benchmark
public String testStringPlus() {
String result = "";
for (int i = 0; i < count; i++) {
result = result + baseString;
}
return result;
}
// 测试2: 使用StringBuilder
@Benchmark
public String testStringBuilder() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < count; i++) {
sb.append(baseString);
}
return sb.toString();
}
// 测试3: 使用StringBuffer
@Benchmark
public String testStringBuffer() {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < count; i++) {
sb.append(baseString);
}
return sb.toString();
}
// 测试4: 使用String.concat()
@Benchmark
public String testStringConcat() {
String result = "";
for (int i = 0; i < count; i++) {
result = result.concat(baseString);
}
return result;
}
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.include(StringConcatBenchmark.class.getSimpleName())
.forks(1) // 启动1个JVM进程
.warmupIterations(3) // 预热3次
.measurementIterations(5) // 正式测试5次
.build();
new Runner(opt).run();
}
}
运行测试
# 打包 mvn clean package # 运行 java -jar target/benchmarks.jar
更复杂的性能测试:集合操作对比
import org.openjdk.jmh.annotations.*;
import java.util.*;
import java.util.concurrent.TimeUnit;
@BenchmarkMode(Mode.AverageTime) // 测试平均执行时间
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Thread)
public class CollectionBenchmark {
private List<Integer> list;
private Set<Integer> hashSet;
private Set<Integer> treeSet;
@Setup
public void setup() {
list = new ArrayList<>();
hashSet = new HashSet<>();
treeSet = new TreeSet<>();
// 初始化数据
Random rand = new Random();
for (int i = 0; i < 10000; i++) {
int value = rand.nextInt(10000);
list.add(value);
hashSet.add(value);
treeSet.add(value);
}
}
// 测试ArrayList查找
@Benchmark
public boolean testArrayListContains() {
return list.contains(5000);
}
// 测试HashSet查找
@Benchmark
public boolean testHashSetContains() {
return hashSet.contains(5000);
}
// 测试TreeSet查找
@Benchmark
public boolean testTreeSetContains() {
return treeSet.contains(5000);
}
// 测试ArrayList排序
@Benchmark
public List<Integer> testArrayListSort() {
List<Integer> copy = new ArrayList<>(list);
Collections.sort(copy);
return copy;
}
// 测试TreeSet排序(自动排序)
@Benchmark
public Set<Integer> testTreeSetSort() {
return new TreeSet<>(list);
}
public static void main(String[] args) throws Exception {
Options opt = new OptionsBuilder()
.include(CollectionBenchmark.class.getSimpleName())
.forks(1)
.warmupIterations(3)
.measurementIterations(5)
.build();
new Runner(opt).run();
}
}
运行结果示例
# JMH version: 1.35
# VM version: JDK 11.0.12, OpenJDK 64-Bit Server VM
Benchmark Mode Cnt Score Error Units
StringConcatBenchmark.testStringBuffer thrpt 5 52345.123 ± 1234.567 ops/s
StringConcatBenchmark.testStringBuilder thrpt 5 67890.456 ± 2345.678 ops/s
StringConcatBenchmark.testStringConcat thrpt 5 23456.789 ± 1234.567 ops/s
StringConcatBenchmark.testStringPlus thrpt 5 12345.678 ± 987.654 ops/s
简易性能测试(不使用JMH)
如果不想使用JMH,可以使用简单的时间测量:
public class SimpleBenchmark {
public static void main(String[] args) {
// 测试StringBuilder vs StringBuffer
int iterations = 100000;
long start = System.nanoTime();
testStringBuilder(iterations);
long end = System.nanoTime();
System.out.println("StringBuilder: " + (end - start) / 1_000_000 + " ms");
start = System.nanoTime();
testStringBuffer(iterations);
end = System.nanoTime();
System.out.println("StringBuffer: " + (end - start) / 1_000_000 + " ms");
}
private static void testStringBuilder(int n) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < n; i++) {
sb.append("test");
}
}
private static void testStringBuffer(int n) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < n; i++) {
sb.append("test");
}
}
}
最佳实践建议
- 使用JMH:对于精确的性能测试,推荐使用JMH框架
- 预热JVM:让JIT编译优化后再测试
- 多次测试:取平均值,避免偶然因素
- 控制环境:关闭其他程序,保持系统空闲
- 关注趋势:不要过分关注绝对数值,比较相对性能
这个案例简单实用,你可以直接复制代码运行测试你的Java代码性能!