全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-11 7 分钟 ✍️ juanwangdev

Java性能测试与基准测试

性能测试验证优化效果,基准测试量化方法性能。

性能测试类型

类型目的工具
基准测试单方法性能JMH
压力测试系统容量JMeter
负载测试正常负载表现JMeter
稳定性测试长时间运行自建脚本

JMH基准测试

什么是JMH

JMH(Java Microbenchmark Harness)是OpenJDK提供的基准测试框架,避免手动测试的常见陷阱。

JMH使用示例

Java
@BenchmarkMode(Mode.AverageTime)  // 平均执行时间
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 5, time = 1)  // 预热5轮
@Measurement(iterations = 10, time = 1)  // 测试10轮
@Fork(1)  // 启动1个进程
@State(Scope.Thread)  // 状态线程隔离
public class StringBenchmark {

    @Benchmark
    public String stringConcat() {
        String s = "";
        for (int i = 0; i < 10; i++) {
            s += i;
        }
        return s;
    }

    @Benchmark
    public String stringBuilder() {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 10; i++) {
            sb.append(i);
        }
        return sb.toString();
    }

    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
            .include(StringBenchmark.class.getSimpleName())
            .build();
        new Runner(opt).run();
    }
}

JMH输出结果

Java
Benchmark                   Mode  Cnt   Score    Error  Units
StringBenchmark.stringConcat avgt  10  450.123 ± 12.34  ns/op
StringBenchmark.stringBuilder avgt  10   85.456 ±  5.67  ns/op

解读:
- Score:平均执行时间
- Error:误差范围
- stringBuilder比stringConcat快5倍

JMH注解说明

注解作用
@BenchmarkMode测试模式:AverageTime、Throughput
@OutputTimeUnit时间单位
@Warmup预热配置:让JIT编译生效
@Measurement测试配置
@Fork进程数:避免进程间影响
@State状态共享级别
@Setup初始化方法
@TearDown清理方法

JMH陷阱避免

Bash
// 陷阱1:死代码消除
@Benchmark
public int wrong() {
    int x = 1 + 2;  // 可能被JIT优化掉
    return x;  // 必须返回
}

// 陷阱2:常量折叠
@Benchmark
public int wrong() {
    return 1 + 2;  // JIT直接返回3
}

// 推荐:使用Blackhole消费结果
@Benchmark
public void correct(Blackhole bh) {
    int x = compute();
    bh.consume(x);  // 防止优化
}

JMeter压力测试

JMeter基本配置

Java
┌─────────────────────────────────────┐
│         JMeter测试计划              │
├─────────────────────────────────────┤
│  Thread Group(线程组)              │
│    - 线程数:100                     │
│    - Ramp-Up:10秒                  │
│    - 循环次数:10                    │
│                                     │
│  Sampler(采样器)                   │
│    - HTTP Request                   │
│                                     │
│  Listener(监听器)                  │
│    - Summary Report                 │
│    - Aggregate Report               │
│                                     │
└─────────────────────────────────────┘

JMeter参数说明

参数说明
线程数并发用户数
Ramp-Up启动全部线程的时间
循环次数每个线程执行次数
吞吐量每秒请求数(TPS)
响应时间平均/最大响应时间
错误率失败请求百分比

JMeter结果分析

text
Summary Report:
+--------+--------+--------+--------+--------+
| Label  | Samples| Average| Error% | TPS    |
+--------+--------+--------+--------+--------+
| HTTP   | 10000  | 50ms   | 0.1%   | 200    |
+--------+--------+--------+--------+--------+

关键指标:
- Samples:总请求数
- Average:平均响应时间
- Error%:错误率(应<1%)
- TPS:吞吐量(每秒请求数)

性能指标分析

核心指标

指标说明标准
TPS/QPS每秒请求数根据业务需求
响应时间平均响应时间<100ms优秀
P99响应时间99%请求响应时间<500ms
错误率失败请求比例<1%
CPU使用率CPU占用<70%
内存使用率内存占用<80%

响应时间分布

text
┌─────────────────────────────────────┐
│        响应时间分布                  │
├─────────────────────────────────────┤
│                                     │
│  P50  = 50ms  (50%请求小于50ms)    │
│  P90  = 80ms  (90%请求小于80ms)    │
│  P99  = 200ms (99%请求小于200ms)   │
│  P999 = 500ms (99.9%请求小于500ms) │
│                                     │
│  P99/P999更能反映用户体验            │
│                                     │
└─────────────────────────────────────┘

压测流程

text
┌─────────────┐
│  确定目标   │ ← TPS、响应时间、并发数
└─────────────┘
      ↓
┌─────────────┐
│  设计场景   │ ← 正常、峰值、极限场景
└─────────────┘
      ↓
┌─────────────┐
│  配置工具   │ ← JMeter线程组、采样器
└─────────────┘
      ↓
┌─────────────┐
│  执行测试   │ ← 分阶段执行
└─────────────┘
      ↓
┌─────────────┐
│  收集结果   │ ← 日志、监控数据
└─────────────┘
      ↓
┌─────────────┐
│  分析优化   │ ← 定位瓶颈,调优
└─────────────┘

监控配合

压测时配合监控:

text
# CPU监控
top -H -p <pid>

# 内存监控
jstat -gc <pid> 1000

# 网络监控
netstat -an | grep <port>

# 系统监控
vmstat 1
iostat -x 1

压测注意事项

  1. 预热阶段:让JIT编译生效,避免冷启动影响
  2. 渐进加压:从低并发逐步增加,避免直接高压
  3. 持续时间:至少10-15分钟,观察稳定性
  4. 隔离环境:独占测试环境,避免干扰
  5. 数据准备:足够测试数据,避免数据量影响

基准测试最佳实践

text
// 1. 预热让JIT生效
@Warmup(iterations = 5)

// 2. 多轮测试取平均值
@Measurement(iterations = 10)

// 3. 多进程避免相互影响
@Fork(3)

// 4. 防止死代码消除
public void test(Blackhole bh) {
    bh.consume(result);
}

// 5. 合理设置状态共享
@State(Scope.Thread)  // 线程隔离
@State(Scope.Benchmark) // 全局共享

注意事项

JMH预热很重要,JIT编译影响结果

压测要渐进加压,避免直接高压崩溃

关注P99而非平均值,反映真实用户体验

压测需在独立环境,避免其他因素干扰

结果需多次验证,单次结果不可靠

要点总结

  1. JMH是基准测试标准工具,避免手动测试陷阱
  2. 基准测试需预热、多轮、多进程
  3. JMeter适合压力测试,关注TPS和响应时间
  4. P99响应时间比平均值更能反映用户体验
  5. 压测需配合监控,全面分析性能表现

📝 发现内容有误?点击此处直接编辑

← 上一篇 Java性能分析工具使用
下一篇 → Java PreparedStatement与批处理
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库