用JBang一步生成Java性能火焰图


火焰图是查找 Java 代码中的瓶颈和性能问题的绝佳工具。

分析性能的一种常用技术是 火焰图。简而言之,火焰图是一种可视化代码的哪些部分消耗更多时间的技术。

火焰图提供了两个有趣的提示:

  1. 堆栈越高,代码中的委托数量就越多。大多数时候,委托并不是一个大的性能问题(JVM 足够聪明,可以内联代码来避免委托),但当数量很大时,人们可能会考虑调查原因。
  2.  框架越宽,完成功能所需的时间就越长。

因此,当使用火焰图查找性能问题时,请查找宽框架或更高的堆栈。

火焰图不会告诉您何时或为何调用该方法或类,而只会告诉您谁在调用它。
您可以自行查找调用原因或应用其他性能分析技术来查找确切原因

生成火焰图步骤:

  1. 安装性能分析器,这是一种分析正在运行的应用程序线程以识别正在运行的帧的工具。这通常意味着查找并下载分析器的源代码
    •  为此类源设置开发人员环境和编译器
    •  编译源代码以生成分析器的本机二进制文件。
  •  以生成为性能分析器提供框架信息(pe 类和方法名称)所需的所有元数据的方式编译应用程序。
  •  同时执行您的应用程序和性能分析器,将性能分析器附加到您的应用程序。
  •  性能分析完成后,提取性能分析器生成的信息。
  •  最后,将提取的信息转换为可查看的火焰图(通常是 HTML 文件)。
    前面的每个步骤都需要安装和设置一个可在您的系统中使用的专用工具。


    实现工具:

    • Async-profiler 是一个专门编写的性能分析器。
    • Ap-loader 是一个库,它作为 Java 代理打包、加载和执行 async-profiler 。

    ap-loader 和 async-profiler 解决了生成火焰图的第一步和最后一步。
     JBang 解决其余步骤:

    • 获取并运行适当版本的 JVM 来运行您的应用程序。
    •  获取代码依赖项、编译代码并在一个步骤中运行它。
    •  如果需要,除了您的应用程序之外,还可以获取额外的依赖项或库并执行 Java 代理。

    JBang与 ap-loader 一起,JBang 可以 一步生成火焰图:

    jbang run --java " 19+"  \
                    --deps org. openjdk jmh: Jmh-generator-annprocess: 1.36 \
                    --javaagent=ap-loader@jvm-profiling-tools/ap-loader=start, event=cpu, file=profile. html
               Myprogram, java


    解释如下:
    命令:

    • –java “19+” 告诉 JBang 使用 Java 19 或更高版本。
    •  –deps … 将 jmh-generator-annprocess 库添加到构建中。这是运行 ap-loader所必需的。
    •  –javaagent=... 指示 JBang 获取并执行 ap-loader  java 代理,该代理获取性能数据并生成火焰图。它还为代理提供配置,如 async-profiler 代码库中所述。

    使用该命令,当您的应用程序结束时,您将  在当前目录中获得一个文件profile.html 。这个文件就是火焰图。

    在某些情况下,您可能需要添加其他参数:

    • 在 MacOS 中,我需要通过添加 –java-options=”-XX:+UnlockDiagnosticVMOptions” –java-options=”-XX:+AllowArchivingWithJavaAgent” 来启用 Java 代理归档
    •  如果您希望 JDK 包显示在火焰图中,您需要确保相应的模块已打开;pe  -R=”–add-opens=java.base/sun.nio.ch=ALL-UNNAMED”、  -R=”–add-opens=java.base/java.io=ALL-UNNAMED” 或 -R= ”–add-opens=java.base/java.lang=ALL-UNNAMED”。
    • 有些人评论说需要一个--enable-preview标志才能让代理工作。但我从来不需要它。

    总结
    使用 JBang,生成火焰图几乎是轻而易举的事。只需在运行命令中添加两个标志即可!