JProfiler 案例 程序 性能 观察 调优 监控

JProfiler结合案例初探全貌

需求分析

当一次又一次的陷入在服务器上跑的程序为什么无法把资源打满的疑惑,为什么明明在计算和存储资源都有富裕的情况下为什么压力测试表现出来的结果,TPS数据都无法差强人意的时候,总会想着说跳出代码从其他角度来观察我们的程序。当局者迷旁观者清,借助工具来观察程序运行的情况有助于我们找到关键点。
对于进程说,性能的瓶颈往往存在于以下几种资源的开销上

  • CPU资源
  • IO资源(硬盘和网络)
  • 内存资源
    这是通用于所有运行在服务器上的进程的,而细化到JAVA程序上,又可以细分为以下几个小点
  • CPU Load
  • JVM内存
  • GC情况
  • 线程阻塞
    ……
    其实大部分情况下,挖性能都可以从以上几个点去挖出性能。但性能和需要的时间是完全成正比的,同样一个功能,支持几十几百个官老爷一个月不一定点点点几下和支持可能达到几千的QPS需要的时间是以几何倍数成长的。在考虑性能优化的同时也不能完全从程序角度去考虑,同时也要考虑上时间成本,人工成本和硬件成本。我认为提前预计半年以后的规模来做设计是最稳妥的考虑,如果要为了一个可能会经历快速迭代变动而且目前可以通过简单的负载均衡来扩展的功能点而花费过多的时间成本来调优我认为是不明智的。

工具介绍

说了这么多废话进入正题。
这个工具是干嘛的?
监控我一个java进程我上述所说的所有情况,以图形的方式来直观展示。
如果没有这个工具怎么做呢?
一样能做,服务器层面上的命令有top,vmstats,free,iostats这些命令来观察服务器的资源消耗情况,程序层面上有jmap,jstack等jdk自带的工具来做监控。但是jstack一个dump就是满屏刷不完的thread,别说死锁了,线程多了我连自己的线程都找不到。实在是难以阅读,图形化界面是非常有必要的。
怎么安装使用破解
自行百度不赘述,我目前是mac系统装了JProfiler8,最新版的10找不到key,实在是穷人买不起,有钱希望能支持下。
我的环境是IDEA JProfiler插件+JProfiler8

案例分析

首先贴上测试代码

package com.huangqq.test;

import java.math.BigInteger;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

/**
 * 在这里想办法把cpu跑满 要能看到cpu的线向上浮动
 */
public class TestCPU {

    public static void main(String[] args) {
        TestCPU t = new TestCPU();
        String input = "我的世界开始下雪 冷的让我无法多爱一天";
        List<String> list = new ArrayList<String>();


        Thread scanThread = new Thread(new Runnable() {
            public void run() {
                // 从键盘接收数据
                Scanner scan = new Scanner(System.in);
                String str=scan.next();
                if(str.equals("stop")){
                    System.exit(0);
                }
            }
        });

        //启动键盘扫描线程
        scanThread.start();

        while (true){
            String hex = t.computeMD5(input);
            list.add(hex);
        }

    }


    /**
     * 计算md5
     * @param input
     * @return
     */
    public String computeMD5(String input){
        try {
            // 生成一个MD5加密计算摘要
            MessageDigest md = MessageDigest.getInstance("MD5");
            // 计算md5函数
            md.update(input.getBytes());
            // digest()最后确定返回md5 hash值,返回值为8为字符串。因为md5 hash值是16位的hex值,实际上就是8位的字符
            // BigInteger函数则将8位的字符串转换成16位hex值,用字符串来表示;得到字符串形式的hash值
            return new BigInteger(1, md.digest()).toString(16);
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }
}

程序的目的有以下几个

  1. 进行计算,大量占用计算资源来看到cpu曲线的浮动
  2. 消耗内存来看到内存的消耗和GC曲线的变化
  3. 启动线程来观察多线程情况thread的tab界面展示情况
  4. 当我观察曲线到满意或者机子已经扛不住我这么折腾的时候从控制台输入stop停止进程

那么这个小程序可以满足我的所有需求,hash计算会消耗大量的CPU资源,同时加入list的操作又会消耗大量的内存资源,内存的大量消耗触发了GC动作,监听stop命令的线程也体现出来了,完美!我们来看下程序运行起来以后的性能图表


短短的几秒我的笔记本已经明显的感觉到了不对劲,赶紧停了。

  1. 首先看Memory
    当我停止我的进程的同时,jvm申请的内存已经达到2.7GB。其中使用了1.28GB。其实这里我有一点非常不明白,jvm所能使用的最大内存在启动时不是已经确定了吗,为什么曲线会动态上升,我本来还以为正常的结果应该会oom掉。
    2.其次看GC情况,纵轴代表的是在an estimate of the total percent of cpu used to collect data.大意是收集垃圾时所消耗的cpu资源?和下方的CPU Load曲线基本所有高峰期都可以对应。从图中可以看出短时间内触发了很多次MinorGC,但并没有改善内存情况,因为我的程序并没有可以收集的垃圾对象?
    3.Threads界面比较简单和直观,反映了我的两条线程正在愉快的runnable状态,相对的如果处于等待Waiting threads会以黄色表示,而如果处于阻塞Blocked threads资源的情况会以红色表示。这里可以用来查看一些线程等待的情况。
    4.CPU情况,除了高峰期和GC情况重合以外也能明显的看得出大部分时期都是处于比较高负荷(40-60)的状态,正常的应用一般很难达到百分10.

一个简单入门使用,还是没有完全理清整个工具怎么使用,可能还是要对jvm的执行细节再深入一些。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 参数设置 在Java虚拟机的参数中,有3种表示方法用“ps -ef |grep "java"命令,可以得到当前Ja...
    九问阅读 9,180评论 2 52
  • 1、 性能调优 1.1、 分配更多资源 1.1.1、分配哪些资源? Executor的数量 每个Executor所...
    Frank_8942阅读 4,585评论 2 36
  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,341评论 11 349
  • “第一次写简书文,马上也要参加实习了,虽然一直也有写笔记的习惯,但是都没有公开,以前写的现在看上去似乎也感觉欠妥,...
    JuLim阅读 281评论 4 0
  • 文 | 风的衣裳 上海滩——十里洋场。你那么猝不及防地闯入了这个灯红酒绿的世界,也闯入了我毫无防备的心里。尽管早就...
    风的衣裳阅读 956评论 50 55