自帶火焰圖的Java性能分析工具Async-profiler


火焰圖
如果你經常遇到 Java 線上性能問題束手無策,看着線上服務 CPU 飆升一籌莫展,發現內存不斷泄露滿臉茫然。別慌,這里有一款低開銷、自帶火焰圖、讓你大呼好用的 Java 性能分析工具 - async-profiler

最近 Arthas 性能分析工具上線了火焰圖分析功能,Arthas 使用 async-profiler 生成 CPU/內存火焰圖進行性能分析,彌補了之前內存分析的不足。在 Arthas 上使用還是比較方便的,使用方式可以看官方文檔。這篇文章介紹 async-profiler 相關內容。

Arthas 火焰圖官方文檔:https://arthas.aliyun.com/doc/profiler.html

async-profiler 介紹

async-profiler 是一款開源的 Java 性能分析工具,原理是基於 HotSpot 的 API,以微乎其微的性能開銷收集程序運行中的堆棧信息、內存分配等信息進行分析。

使用 async-profiler 可以做下面幾個方面的分析。

  • CPU cycles
  • Hardware and Software performance counters like cache misses, branch misses, page faults, context switches etc.
  • Allocations in Java Heap
  • Contented lock attempts, including both Java object monitors and ReentrantLocks

我們常用的是 CPU 性能分析和 Heap 內存分配分析。在進行 CPU 性能分析時,僅需要非常低的性能開銷就可以進行分析,這也是這個工具的優點之一。

在進行 Heap 分配分析時,async-profiler 工具會收集內存分配信息,而不是去檢測占用 CPU 的代碼。async-profiler 不使用侵入性的技術,例如字節碼檢測工具或者探針檢測等,這也說明 async-profiler 的內存分配分析像 CPU 性能分析一樣,不會產生太大的性能開銷,同時也不用寫出龐大的堆棧文件再去進行進一步處理,。

async-profile 目前支持 Linux 和 macOS 平台(macOS 下只能分析用戶空間的代碼)。

  • Linux / x64 / x86 / ARM / AArch64
  • macOS / x64

async-profiler 工具在采樣后可以生成采樣結果的日志報告,也可以生成 SVG 格式的火焰圖,在之前生成火焰圖要使用 FlameGraph 工具。現在已經不需要了,從 1.2 版本開始,就已經內置了開箱即用的 SVG 文件生成功能。

其他信息可以看官方文檔:https://github.com/jvm-profiling-tools/async-profiler

async-profiler 安裝

# 從阿里雲下載jar包
curl -O https://arthas.aliyun.com/arthas-boot.jar
# 運行
java -jar arthas-boot.jar

arthas-boot.jar中直接內置了profiler

async-profiler 使用

[arthas@69686]$ profiler execute 'start'
Started [cpu] profiling
[arthas@69686]$ profiler execute 'stop,file=/Users/admin/Desktop/result.svg'
OK

async-profiler 案例

上面說完了 async-profiler 工具的作用和使用方式,既然能進行 CPU 性能分析和 Heap 內存分配分析,那么我們就寫幾個不一般的方法分析試試看。看看是不是有像上面介紹的那么好用。

Java 案例編碼

很簡單的幾個方法,hotmethod 方法寫了幾個常見操作,三個方法中很明顯 hotmethod3 方法里的生成 UUID 和 replace(需要正則匹配)操作消耗的 CPU 性能會較多。allocate 方法里因為要不斷的創建長度為 6萬的數組,消耗的內存空間一定是最多的。

import java.util.ArrayList;
import java.util.Random;
import java.util.UUID;

/**
 * <p>
 * 模擬熱點代碼
 *
 * @Author niujinpeng
 */
public class HotCode {

    private static volatile int value;

    private static Object array;

    public static void main(String[] args) {
        while (true) {
            hotmethod1();
            hotmethod2();
            hotmethod3();
            allocate();
        }
    }

    /**
     * 生成 6萬長度的數組
     */
    private static void allocate() {
        array = new int[6 * 1000];
        array = new Integer[6 * 1000];
    }

    /**
     * 生成一個UUID
     */
    private static void hotmethod3() {
        ArrayList<String> list = new ArrayList<>();
        UUID uuid = UUID.randomUUID();
        String str = uuid.toString().replace("-", "");
        list.add(str);
    }

    /**
     * 數字累加
     */
    private static void hotmethod2() {
        value++;
    }

    /**
     * 生成一個隨機數
     */
    private static void hotmethod1() {
        Random random = new Random();
        int anInt = random.nextInt();
    }
}

CPU 性能分析

$ profiler start
Started [cpu] profiling

CPU 使用火焰圖

關於火焰圖怎么看,一言以蔽之:火焰圖里,橫條越長,代表使用的越多,從下到上是調用堆棧信息。在這個圖里可以看到 main 方法上面的調用中 hotmethod3 方法的 CPU 使用是最多的,點擊這個方法。還可能看到更詳細的信息。

hotmethod3 CPU 火焰圖
可以看到 replace 方法占用的 CPU 最多,也是程序中性能問題所在,是需要注意的地方。

Heap 內存分析

還是上面運行的程序,這次分析內存使用情況。

profiler start --event alloc

得到的 svg 文件使用瀏覽器打開,可以看到內存分配情況。

內存分配火焰圖

依舊是橫條越長,代表使用的越多,從下到上是調用堆棧信息。從圖里可以看出來 main 方法調用的 allocate 方法使用的內存最多,這個方法里的 Integer 類型數組占用的內存又最多,為 71%。

文中測試代碼已經上傳到 Github:https://github.com/niumoo/lab-notes

站在巨人肩膀上摘蘋果

https://blog.csdn.net/u013735734/article/details/103452212


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM