Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

更好的profiler命令支持 #2164

Closed
hengyunabc opened this issue Apr 26, 2022 · 15 comments
Closed

更好的profiler命令支持 #2164

hengyunabc opened this issue Apr 26, 2022 · 15 comments
Labels
help wanted Extra attention is needed

Comments

@hengyunabc
Copy link
Collaborator

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

  • 需要重新考虑支持的参数
  • 支持async-profiler 的新功能
@Winson-Huang
Copy link
Contributor

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

@Winson-Huang
Copy link
Contributor

Winson-Huang commented Aug 10, 2023

整体思路

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 格式。

@hengyunabc
Copy link
Collaborator Author

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

@Winson-Huang
Copy link
Contributor

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

@hengyunabc
Copy link
Collaborator Author

现在在应用的控制台会打印,可能要处理下:

Unknown argument: framebuf

参考: #2625 (comment)

@Winson-Huang
Copy link
Contributor

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

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

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

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

@hengyunabc
Copy link
Collaborator Author

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

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

@Winson-Huang
Copy link
Contributor

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

@Winson-Huang
Copy link
Contributor

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

@hengyunabc
Copy link
Collaborator Author

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

@Winson-Huang
Copy link
Contributor

关于 fdtransfer 选项的讨论

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

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

@hengyunabc

@Winson-Huang
Copy link
Contributor

关于 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。

@hengyunabc
Copy link
Collaborator Author

关于 fdtransfer 选项的讨论

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

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

@hengyunabc

这个可以忽略。

@hengyunabc
Copy link
Collaborator Author

关于 collect action 的讨论

-d 参数是从这里加入的: #1197

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

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

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

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

This was referenced Sep 23, 2023
@Winson-Huang
Copy link
Contributor

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants