一、性能优化的总体目标
核心目标:
用尽可能少的资源(CPU、内存、IO、网络),实现更高的吞吐量、更低的响应时间、更稳定的系统。
性能优化维度:吞吐量、响应时间、可伸缩性、稳定性。
- 吞吐量优化(Throughput) — 单位时间处理更多请求;
- 响应时间优化(Latency) — 缩短单个请求的处理时间;
- 可伸缩性优化(Scalability) — 支持更多并发用户、任务;
- 稳定性优化(Stability) — 系统在高负载或异常情况下仍稳定。
二、性能优化的三层策略
| 层级 | 策略类型 | 核心思想 | 示例 | | ————- | ——– | —————– | ——————— | | 架构层(宏观) | 结构优化 | 从系统设计入手,减少瓶颈、分层解耦 | 分布式缓存、异步化、CQRS、分库分表 | | 代码层(中观) | 算法与实现优化 | 提升算法效率、减少锁、内存分配 | 使用并发容器、避免不必要对象创建 | | JVM 层(微观) | 参数调优与 GC | 调整虚拟机内存结构、GC策略 | 使用 G1/ZGC、调整堆大小、优化线程栈 |
三、性能优化的两种方法论
自顶向下
核心思想
自顶向下是一种更偏向业务层和用户体验或感知的一种性能分析方法。比如业务请求变慢啦、页面卡顿或报错。一般是由用户或客户反馈上来,并逐步排查
示例流程
1
2
3
4
5
6
7
8
9
用户反馈:订单提交慢
↓
APM分析:订单服务响应时间800ms
↓
方法分析:库存检查耗时600ms
↓
SQL分析:库存查询缺少索引
↓
优化:添加复合索引
排查路径
使用日志/分布式追踪(Zipkin/Jaeger/Elastic APM)定位哪个请求或哪个服务链路变长。
1
客户端 → 负载均衡 → 网关 → 服务(HTTP/Netty) → DB/缓存/外部调用
收集运行指标
- 应用级指标:请求耗时分位(p50/p95/p99)、QPS、错误率。
- 系统级指标:CPU、内存、网络带宽、磁盘 IO、负载、上下文切换、线程数、文件描述符等。
针对性采样剖析
在问题时间窗口做线程快照(thread dump)、火焰图或采样 profiler(async-profiler / JFR)。重点只在疑似慢的请求路径上做,避免海量噪音。
分析调用链并定位热点
观察慢请求的调用路径,找出耗时方法(IO、数据库、序列化、长锁、循环)并确认是真正瓶颈(占比高/可复现)。
验证并修复
小范围改进(缓存、批量、减少同步、改异步),再衡量性能指标与用户感知。
常用工具
- 应用层:JProfiler、VisualVM、Arthas
- JVM层:GC日志分析、堆转储分析
- 系统层:top、iostat、netstat
适用场景
- 生产环境问题排查
- 系统整体性能评估
- 用户反馈的性能问题
自底向上
核心思想
从底层指标和系统资源出发,一般由监控系统触发,比如内存使用率,CPU负载高。触发告警系统,通知到运维或开发,然后向上分析对业务的影响
示例流程
1
2
3
4
5
6
7
8
9
监控告警:CPU使用率持续90%
↓
perf分析:大量时间在序列化操作
↓
火焰图:JSON序列化占用50% CPU
↓
代码分析:频繁序列化大对象
↓
优化:缓存序列化结果、使用更高效的序列化库
底层采样
- CPU:采样 profiler(火焰图)找最热方法;若是系统调用(例如 epoll_wait、writev)则说明 IO 瓶颈。
- 内存:allocation profiler 或 MAT/HPROF 堆转储分析(大对象、类加载、多余持有)。
- GC:jstat/jcmd 或 GC 日志、G1/ZGC 等指标,看 Pause、Young/Tenured 分布。
- 锁竞争:block profiler 或 jstack 分析 BLOCKED/WATING 状态和锁持有栈。
从热点回溯调用链
许多 profiler(async-profiler)支持同时输出火焰图(按方法)和调用图(calltree),用于把底层热点映射成调用链。
定位触发代码/数据模式
例如:发现大量短时分配,回溯到某个循环中构造对象或使用 String + concat;发现锁竞争,找到哪个 synchronized/Lock 导致串行化。
修复并验证
优化算法、复用对象(对象池 / 重写为原始类型)、减少同步粒度、改为无锁/并发结构、改异步 IO、批量化。
常用工具
- CPU分析:perf、async-profiler、火焰图
- 内存分析:MAT、jmap、jstat
- 线程分析:jstack、Thread Dump分析
适用场景
- 系统资源异常(CPU飙高、内存溢出)
- 预防性优化
- 微服务架构的容量规划
四、性能优化的系统方法
架构优化
缓存机制
- 本地缓存:Guava Cache / Caffeine;
- 分布式缓存:Redis、Memcached;
- 缓存策略:LRU、TTL、热点缓存、布隆过滤器防穿透。
异步与并行化
- 使用线程池、CompletableFuture;
- 异步消息队列(Kafka/RabbitMQ);
- Reactor 模型(Netty、Spring WebFlux)。
服务拆分
- 微服务化、按功能模块分层;
- 减少接口依赖;
- 降低单体压力。
- 数据库层优化
数据库设计
- 分库分表、读写分离;
- 批量操作替代单条执行。
IO与网络
- 使用 NIO / Netty;
- 使用连接池(HTTP、DB);
- 减少序列化/反序列化开销(JSON→Protobuf)。
代码层优化
算法与数据结构
- 避免 O(n²);
- 优化集合选择(ArrayList vs LinkedList vs HashMap);
- 减少不必要同步。
对象与内存
- 避免频繁创建对象(可用对象池);
- 循环中多次拼接使用 StringBuilder 替代字符串拼接;
- 尽量复用对象(尤其在循环中)。
锁与并发
- 使用无锁结构(CAS、Atomic、LongAdder);
- 尽量缩小锁粒度;
- 减少 synchronized,使用 ReentrantLock;
- 使用并发集合(ConcurrentHashMap)。
异常与日志
- 避免频繁抛出异常;
- 控制日志量与级别;
- 异步日志输出(Log4j2 AsyncAppender)。
流与集合操作
- 避免过度 Stream 嵌套;
- 使用并行流时考虑 CPU 核数;
- 注意装箱/拆箱。
JVM 层优化
- GC 策略选择
- 小内存、低延迟:G1;
- 大堆、低延迟:ZGC;
- 低配置机器:ParallelGC;
- 使用 -XX:+PrintGCDetails 观察。
内存分配
- 年轻代、老年代比例(-Xmn);
- 元空间(Metaspace);
- 栈大小(-Xss);
- 堆外内存(DirectBuffer)。
线程调优
- 线程池参数;
- IO密集 vs CPU密集;
- 避免过多线程上下文切换。
JIT 优化
- 利用即时编译器(C2);
- 热点方法内联;
- 避免过度反射。
