Java性能测试案例怎么简单实操

wen java案例 29

本文目录导读:

Java性能测试案例怎么简单实操

  1. 环境准备
  2. 实战案例:字符串拼接性能测试
  3. 更复杂的性能测试:集合操作对比
  4. 运行结果示例
  5. 简易性能测试(不使用JMH)
  6. 最佳实践建议

我来提供一个简单实用的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");
        }
    }
}

最佳实践建议

  1. 使用JMH:对于精确的性能测试,推荐使用JMH框架
  2. 预热JVM:让JIT编译优化后再测试
  3. 多次测试:取平均值,避免偶然因素
  4. 控制环境:关闭其他程序,保持系统空闲
  5. 关注趋势:不要过分关注绝对数值,比较相对性能

这个案例简单实用,你可以直接复制代码运行测试你的Java代码性能!

抱歉,评论功能暂时关闭!