Java 性能方法论
Java 性能工作的正确顺序:定义指标、复现、剖析、改动、回归,避免过早优化。
#type / concept
#status / growing
#tech / dev
#resource / java
[!info] 关联笔记
Java 性能方法论
这个概念为什么出现
“感觉慢”不能指导改代码。Java 有 JIT、GC、预热,错误基准会指向错误热点。方法论比某个收集器参数更重要。
[!abstract] 一句话理解 先定义用户指标与 SLO,再稳定复现,用剖析找热点,小步改动并回归;禁止一次
System.nanoTime包装的伪基准下结论。
最小可观察示例
场景:对比两种拼接在错误基准下的误导(教学)
public class BadBenchmark {
static String plus() {
String s = "";
for (int i = 0; i < 1000; i++) s += i;
return s;
}
static String builder() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) sb.append(i);
return sb.toString();
}
public static void main(String[] args) {
long t1 = System.nanoTime();
plus();
long t2 = System.nanoTime();
builder();
long t3 = System.nanoTime();
System.out.println("plusNs=" + (t2 - t1));
System.out.println("builderNs=" + (t3 - t2));
System.out.println("note=not-a-real-benchmark");
}
}
javac BadBenchmark.java && java BadBenchmark
期望:打印两段耗时,并明确这不是科学基准(无预热、无迭代统计、JIT 未稳定)。
结合场景再看三个关注点
- 预热与多轮统计必要。
- JMH 才是微基准常用框架。
- 系统级指标(延迟分位、吞吐、错误率)优先于微基准。
核心概念与准确模型
1. 工作流
指标 → 复现 → 剖析(JFR/采样)→ 假设 → 改动 → 回归
2. 常见热点
分配过多、锁竞争、IO、错误缓存、正则、日志
3. 工具
JFR、async-profiler、JMH、指标系统
边界情况与反直觉行为
- 开发机与生产硬件差异。
- GC 停顿表现为“接口毛刺”。
- 优化可读性崩溃却只换 2% → 不值得。
常见误区
[!warning] 常见误区:先改代码再想指标 没有基线就没有优化。
工程实践
- SLO/SLA 写清。
- 负载测试贴近真实。
- 每次只改一类变量。
- 把剖析火焰图留档。
本节总结
- 方法论 > 玄学参数
- 测量与回归
- 微基准慎用
自测题
- 为什么需要预热?
- 延迟看平均值够吗?
参考答案
- JIT 与缓存升温会改变稳态性能。
- 不够;应看分位数(P95/P99)与错误率。
延伸阅读与资料来源
| 资料 | 类型 | 支撑内容 |
|---|---|---|
| JMH | 工具 | 微基准 |
| JDK Flight Recorder | 官方 | 剖析 |