Home Java性能分析第一节 - 策略,方法 和 方法论.
Post
Cancel

Java性能分析第一节 - 策略,方法 和 方法论.

一、性能优化的总体目标

核心目标:

用尽可能少的资源(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);
  • 热点方法内联;
  • 避免过度反射。

weixin.png

公众号名称:怪味Coding
微信扫码关注或搜索公众号名称
This post is licensed under CC BY 4.0 by the author.