跳转至

性能工程

面试追问地图

主问题 必讲关键点 下一层追问
目标 SLO、负载、基线、瓶颈 吞吐和延迟如何权衡
JMH 预热、fork、DCE、常量折叠 Blackhole、状态作用域
压测 开放/封闭模型、数据分布、协调遗漏 P99、容量拐点
剖析 采样、on/off-CPU、调用栈 JFR 与 async-profiler
验证 单变量、对照、置信度、资源账单 瓶颈是否转移

一、目标与基线

性能优化前要定义什么?

先定义业务负载和目标:请求比例、数据规模、并发模型、吞吐、P95/P99、错误率和资源成本。平均延迟正常不能证明用户体验正常,长尾请求会占住线程和连接并放大排队。

优化从基线开始:固定硬件、JDK、参数、数据集和依赖版本,记录 CPU、内存、GC、磁盘、网络和下游指标。没有基线的“快了 30%”无法复现,也不知道代价是否转移到别处。

二、微基准与服务压测

Java 微基准为什么要用 JMH?

JVM 有分层编译、方法内联、常量折叠和死代码消除,直接在循环前后读取时间很容易测到被优化掉的代码。JMH 提供预热、测量迭代、独立 fork、状态隔离和结果消费机制。

  • 返回结果或使用 Blackhole,防止死代码消除。
  • 输入不能都是编译期常量,否则可能测到常量折叠结果。
  • 用多个 fork 隔离 JVM 状态,报告方差,不只挑最好一次。
  • 微基准只证明局部代码路径,不代表应用吞吐;锁、缓存和分配行为要按真实并发度建模。

服务压测模型怎样设计?

封闭模型由固定并发用户“完成后再发下一次”,系统变慢时发压自然下降,可能掩盖过载;开放模型按计划到达率发请求,更接近外部流量。工具若只在上一次响应后记录下一次预期发送,会产生协调遗漏,低估排队和长尾。

压测要逐步升流量,找到延迟陡升、错误增加或资源饱和的容量拐点;数据热度、读写比例、缓存命中率和第三方限额应接近生产。压测环境不能承受真实规模时,应明确外推假设。

三、剖析与验证

火焰图怎样定位 CPU 热点?

采样分析器定期抓取线程栈,火焰图横向宽度表示样本占比,不表示时间顺序。先看宽平台定位热点方法,再结合调用来源、分配和锁事件判断根因。

CPU 火焰图看运行热点;off-CPU 分析关注锁等待、I/O 和 sleep。JFR 适合持续低开销记录 JVM/GC/锁/分配事件,async-profiler 适合按需采样 CPU、分配和锁;两者与指标、日志共同形成证据链。

怎样证明性能优化有效?

一次只改变一个主要变量,在相同负载下重复对照,比较吞吐、分位延迟、错误率和资源消耗。优化后继续升压确认新瓶颈,并做正确性回归。减少 20% CPU 却让 P99、内存或下游 QPS 恶化,不是完整的优化结论。

参考资料