为什么需要 Profiling
采样(Sampling)是性能分析的起点,它能快速呈现应用执行的整体视图——哪些方法在执行、总耗时大致多少。但采样有一个关键局限:它只告诉你方法占用了多少时间,却无法告诉你这个方法被调用了多少次。
举个例子:一个方法单次执行只需要 50 毫秒,但如果在某个功能中被重复调用了 1000 次,总耗时就会达到 50 秒。采样只会显示该方法总共占用了 50 秒,而不会告诉你是因为重复调用导致的。这种场景下,如果只依赖采样,你很可能会误判:以为是算法本身慢,却忽略了“重复执行”这个真正的根因。
Profiling(也叫 Instrumentation)就是为了弥补这个不足而生的。它能精确记录每一个方法的调用次数、每次执行的时间,让你看清到底是“慢”还是“多”。
Profiling 的适用场景
Profiling 不应该替代采样,而是采样的后续步骤。在采样已经帮你锁定了“嫌疑区域”之后——比如某个端点响应慢,而堆栈显示大部分时间花在某个包的类中——你就可以用 Profiling 对这片区域进行“显微镜式”分析。
典型适用场景包括:
- 发现某个方法总耗时异常高,但不确定是一次慢调用还是多次快调用。
- 怀疑框架或依赖库动态生成的代码存在重复调用(例如 Feign 客户端、JPA 代理等)。
- 调优已知逻辑,验证重构后调用次数是否减少。
实操步骤:在 VisualVM 中配置 Profiling 过滤规则
以 VisualVM 为例,Profiling 需要在 Profiler 标签页中进行。关键步骤:
- 启动应用和 VisualVM,确保应用以
-Djava.rmi.server.hostname=localhost启动以便连接。 - 在左侧进程列表中选中目标进程,切换到 Profiler 标签。
- 默认情况下,Profiling 会拦截整个应用的所有类,这会导致巨大的性能开销。必须手动限定范围:在右侧的过滤框中输入需要分析的包或类。
过滤规则语法非常简单:
# 匹配单个包下的所有类
com.example.*
# 匹配包及其所有子包
com.example.**
# 匹配具体类名
com.example.controllers.DemoController
每条规则单独一行。对于 Spring 应用,通常需要同时分析应用自己的代码和关键依赖(如 feign.**

1279

被折叠的 条评论
为什么被折叠?



