[alibaba/arthas]更好的profiler命令支持

2025-11-12 354 views
2

目前 https://github.com/jvm-profiling-tools/async-profiler 已经发布了多个2.*新版本。arthas里的集成是据比较旧版本1.*设计的,有很多新的特性没有支持。

  • 需要重新考虑支持的参数
  • 支持async-profiler 的新功能

回答

8

此任务已被 @Winson-Huang 认领,欢迎交流。

2
整体思路

Arthas 的 profiler 命令是在 ProfilerCommand 类中通过调用 async-profiler 的 Java API(位于 one.profiler 包中)实现的。目前两者在使用上有两点主要差异。首先,一般来说 Arthas 在启动时指定目标进程,在 CLI 内执行的命令均作用于指定的进程,命令中不必指定进程标识,但对于 async-profiler,其目前最新正式版 v2.9 的 CLI(在 profiler.sh 脚本中实现)仍需要每次执行命令时指定进程标识。此外,Arthas 的 profiler 命令具体选项也与 async-profiler CLI 的选项不完全一致。

async-profiler 的官方文档中提到 profiler.sh 脚本的实际作用是将 CLI 输入转化为 JVM TI 格式参数进而控制 async-profiler 的行为,完整的参数列表位于 arguments.cpp 文件中。而参考源代码注释Github Discussion,其 Java API 中的 execute 方法也是通过接收这种格式的参数来控制 async-profiler 的。Arthas 实现 profiler 命令的主要思路也正是将用户的 CLI 输入转化为 JVM TI 格式参数后再调用 API 中的 execute 方法。

可以看出,Arthas profiler 命令相关模块的作用与 async-profiler 的 profiler.sh 脚本比较相似,然而,由于 async-profiler 已产生多个版本更新,以及一些其他因素,两者产生了上文指出的差异。考虑到与上游保持一致的诸多好处(不引入新的复杂性,无需自行设计 CLI 外在行为,可以复用上游项目的用户文档),同时考虑到尽量使 Arthas 向后兼容(不破坏已有的用户习惯),完成本任务的整体思路是:

  1. 参考 profiler.sh 脚本,在 Arthas 中实现 profiler 命令的新功能,尽量保持这些新功能与 shell 脚本的外在行为一致,在改动的代码涉及已有功能时,尽量保证与旧版 profiler 命令格式的兼容性。

  2. 在完成 shell 脚本行为的移植工作后,考虑利用 Java API 在 Arthas 中实现一些上游未提供但可以为用户带来便利的 CLI 格式。

3
  • https://github.com/async-profiler/async-profiler/issues/633 可以考虑支持这个
2

目前大部分功能实际上在我的本地仓库已经完成了,我的计划是按 action 逐个提交 PR 进行讨论和细化。

9

@hengyunabc 关于 framebuf 选项,目前 Arthas 中仍存在,但 async-profiler 2.9 版本已经移除了此选项,需要确定在 Arthas 中如何处理。

首先,此选项大概率不是 issue #2625 中提到的无法生成火焰图的原因,我的测试结果和您提到的 comment 一样,火焰图可以正常生成。

然后,此选项确实会导致出现没有用处的 warning 信息,要消除此信息,只要不将 framebuf 参数加入 JVM TI 字符串即可。

最简单的方式是直接将此选项和相关变量直接移除,但这会破坏 Arthas 的向后兼容。第二种方式是让 Arthas 仍接收此选项,但不传递给 async-profiler 且不给出任何警告。最复杂的方式是在第二种方式的基础上,若检测到 framebuf 选项,则为命令结果添加一个警告信息并输出到 arthas 的 CLI。

7

@hengyunabc 关于 framebuf 选项,目前 Arthas 中仍存在,但 async-profiler 2.9 版本已经移除了此选项,需要确定在 Arthas 中如何处理。

可以直接去掉这个选项,因为 arthas 自带的 async-profiler 是匹配的。基本不存在用新版本 arthas,使用旧版本的 async-profiler so 的情况。

3

其实我的意思是,如果直接去掉此选项,那么使用旧版本 arthas 时的那些带有 framebuf 选项的命令就不适用与新版本 arthas 了。不过如果 arthas 绝大部分情况是用手动输入命令进行控制,而没有 arthas 命令脚本这种输入形式的话,是不是不太需要考虑这种向后兼容性?

2

Arthas 的文档中没有明确说这一点,是不是 Arthas 本身没有命令脚本这种输入形式?

2

framebuf 是一个很少使用的参数,并且没有软件能做到旧版本的完全兼容。可以直接去掉。

8
关于 fdtransfer 选项的讨论

在 shell 脚本的 start/resume action(L347)处理流程中,在启动 profiler 之前会根据 --fdtransfer 选项决定是否启动 fdtransfer 工具。该工具用于在低权限环境(容器环境)下响应 perf 请求,但 Java API 中未提供启动该工具的方法,Arthas 中未实现此选项也未包含 fdtransfer 工具。是否要实现该选项,以及如何实现该选项,有待进一步讨论。

根据 Discussion,无法从待分析的 Java 进程本身启动该工具,也就是不能利用织入的代码启动该工具,一种可行的办法是 Arthas 进程本身使用高权限启动,并启动 fdtransfer 工具。这种实现方式已经超出了 Arthas profiler 命令本身的范畴,我可能无法在 OSPP 的期限内完成。

@hengyunabc

4
关于 collect action 的讨论

在 profiler.sh 脚本中,L233 --timeout --loop 这两个选项的设计有些奇怪。timeout 在行为上与 duration 有些类似,功能上也有些重复。loop 的作用是让 profiler 持续执行,但每隔一段时间就将【这一段时间内】的分析结果输出到文件。在 async-profiler 中,PARAMS 变量仅用于 start、resume、check、collect 这 4 个 ACTION,DURATION 变量仅用于 collect。并且当 ACTION 为 collect 时,如果 timeout 和 loop 这两个选项有效,ACTION 会被设定为 start。也就是说,timeout 和 loop 选项实际上只会对 start、resume、check 有效。可以看出 async-profiler 在 collect、duration、timeout、loop 选项/action 上的处理有些混乱。关于这两个选项的详细用法可以参考 What does "timeout" option do ? split profiling into multiple JFR files

目前在 Arthas 中,start 与 async-profiler 的 collect action 很类似,反而不存在与 async-profiler 的 start action 完全对应的 action。到底如何实现这两个 action 有待详细讨论。

一种方式是尽量模拟 async-profiler 的行为。也就是把 start action 修改为与 duration 无关的 action,且接收 timeout 和 loop 这两个选项。然后再添加 collect action 代替当前 start 的行为且不接收这两个参数。

另一种方式是让 arthas 把 start 和 collect 视为同一个 action。在 timeout 和 loop 选项有效时让 duration 仍然起作用,这种情况下一些选项组合产生的行为会比较混乱:比如设定 loop 为 5s 但同时指定了 duration,在 async-profiler 中总是会忽略 duration,但 Arthas 仍会在 duration 时间之后停止 profiler。

9
关于 fdtransfer 选项的讨论

在 shell 脚本的 start/resume action(L347)处理流程中,在启动 profiler 之前会根据 --fdtransfer 选项决定是否启动 fdtransfer 工具。该工具用于在低权限环境(容器环境)下响应 perf 请求,但 Java API 中未提供启动该工具的方法,Arthas 中未实现此选项也未包含 fdtransfer 工具。是否要实现该选项,以及如何实现该选项,有待进一步讨论。

根据 Discussion,无法从待分析的 Java 进程本身启动该工具,也就是不能利用织入的代码启动该工具,一种可行的办法是 Arthas 进程本身使用高权限启动,并启动 fdtransfer 工具。这种实现方式已经超出了 Arthas profiler 命令本身的范畴,我可能无法在 OSPP 的期限内完成。

@hengyunabc

这个可以忽略。

5
关于 collect action 的讨论

-d 参数是从这里加入的: https://github.com/alibaba/arthas/issues/1197

当时把 -d 参数加到 start action 里,考虑的是简化用户的操作,不要加入太多的 action。

但目前来看 profiler command 的功能已经非常复杂,完全可以对标 async-profiler的脚本参数了。

所以,可以考虑这个方案:

一种方式是尽量模拟 async-profiler 的行为。也就是把 start action 修改为与 duration 无关的 action,且接收 timeout 和 loop 这两个选项。然后再添加 collect action 代替当前 start 的行为且不接收这两个参数。

5

这个 issue 基本上已经完成了,有需要修改的地方可以再联系我 @hengyunabc