性能分析

Note

文档的配方部分以目标为核心,尽量减少对基础知识的说明。

目标

我想对 sbt 进行性能分析,以了解它将时间花在了哪里。

解决方案:追踪

  1. 如有现有服务器,先将其关闭:sbt shutdown
  2. 使用 --server --traces 运行命令
$ sbt --server --traces compile
....
$ ls target/traces/build.trace
target/traces/build.trace

这会生成 Chrome 追踪文件 target/traces/build.trace,可使用 Perfetto 查看,显示每个任务所耗费的时间。

解决方案:计时

  1. 如有现有服务器,先将其关闭:sbt shutdown
  2. 使用 --server --timings 运行命令
$ sbt --server --timings compile
....
Total time: 4116 ms
  aaa-build / Compile / compileIncremental      : 731 ms
....

这会在终端输出任务计时信息。

解决方案:火焰图

安装 async-profiler,将 asprofjfrconv 添加到 PATH 中:

$ ln -s $HOME/Applications/async-profiler-4.2/bin/asprof $HOME/bin/asprof
$ ln -s $HOME/Applications/async-profiler-4.2/bin/jfrconv $HOME/bin/jfrconv
  1. 关闭所有可能影响性能分析的程序,并在一个终端中运行 sbt

  2. 在另一个终端运行 jps,确认 sbt 的进程 ID

    $ jps
    92746 sbt-launch.jar
    92780 Jps
    
  3. 使用持续时间标志运行 asprof-d 60 表示 60 秒:

    $ asprof -d 60 -f /tmp/flamegraph.jfr <process id>
    

    这会生成一个 JFR(Java Flight Recorder)文件。

  4. 按如下方式运行 jfrconv,将 *.jfr 文件转换为火焰图:

    $ jfrconv --lines /tmp/flamegraph.jfr /tmp/flamegraph.html
    

进阶:JVM 分析

您可以使用 VisualVM 等性能分析器来识别实现层面的计时信息。

  1. 如有现有服务器,全部关闭:sbt shutdownall
  2. 使用 --server 启动 sbt 会话
  3. 启动 VisualVM,双击 xsbt.boot.Boot
  4. 切换到 Sampler 标签页,点击 CPU
  5. 在 sbt shell 中运行命令
  6. 点击 Sampler 标签页中的 Stop 按钮

名为 pool-n-thread-m 的线程即为任务线程。