• 自带火焰图的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
    

    关于火焰图怎么看,一言以蔽之:火焰图里,横条越长,代表使用的越多,从下到上是调用堆栈信息。在这个图里可以看到 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

    https://www.cnblogs.com/leihuazhe/p/11630466.html

  • 相关阅读:
    说一下Mysql索引
    B树、B-树、B+树、B*树之间的关系
    Mybatis Plus 的优点
    JVM垃圾回收机制
    Java中的集合
    MQ 面试题
    Redis 双写一致性
    Redis 主从复制
    C#中Abstract和Virtual的区别
    C#设计模式(2)——简单工厂模式
  • 原文地址:https://www.cnblogs.com/yuluoxingkong/p/15076549.html
Copyright © 2020-2023  润新知