该方案旨在解决批量跑FreeSDK压力测试脚本的同时自动监控每个压测方法CPU、内存信息并存到指定文件中的问题,替换原先人工观察CPU、内存再做记录的繁琐工作,给予测试工作提供更大的方便。
1.计算CPU的占用率:
CPU占用率:指进程在一个时间段内消耗的CPU时间与该时间段长度的比值。
所以的CPU的计算公式如下:
T:某个时间段(就是要计算这个时间段的CPU使用率)
W:在这个时间段中CPU处于工作状态的时间
I:在这个时间段中CPU处于空闲状态的时间
CPU%=W/T*100% 或
CPU%=(T-I)/T*100%
CPU的时间分为用户态和内核态即userTime和kernelTime。其中还有空闲态idleTime,,但是当CPU在空闲状态时,kernelTime包含了idleTime。所以一段时间内CPU的总时间SystemTime=kernelTime+userTime,CPU的工作时间为BusyTime=kernelTime+userTime-idleTime。
CPU%=BusyTime/SystemTime。
获取CPU系统的占用率即获取windows平台各个CPU的时间状态并计算。
2.代码操作流程:
通过Windows的wmic命令下读取进程的CPU各个状态(注:通过wmic命令获取的进程的是系统的进程,而不是单独的javaw.exe进程),具体操作如下图:

全网最全获取JVM(javaw.exe进程)的CPU占用率

可以打开Perfmon.exe性能监视器观察到,CPU占用率先逐渐升高,再平稳一段时间,最后逐渐下降。
1.    在上升期,CPU上升到正常值后由于算法第一帧的原因,会有一小段持续升高,所以在上升期过滤的时间比下降期过滤的时间多。
2.    过滤掉上升期的时间后即开启一个线程,读取CPU的kernelTime,userTime,idleTime。读取一次后给该线程加锁进入等待。
3.    在过滤下降期时间前再开启一个线程,释放第一个线程的锁,使第一个线程再次读取过滤前的CPUkernelTime,userTime,idleTime各个时间并计算。计算公式为:CPU占用率= (BusyTime(第二次读取)-BusyTime(第一次读取))/(SystemTime(第二次读取)-SystemTime(第一次读取))。计算出的CPU占用率即开启第一个线程后中间等待时间的CPU占用率。
4.    由于无法获取单独的Javaw.exe进程的CPU占用率,只能获取系统的CPU占用率,图中红色部分为该系统不运行Javaw.exe进程时的CPU占用,所以最后CPU占用率应该再减去其他进程的CPU占用率。(注:以该方式跑批量压测方法时不能运行浏览电脑任何软件或网页,否则其他进程的CPU占用会大幅升高影响结果)
具体代码

public  class JavaInformations {
    public static final double BENCHMARK_ZERO_VALUE = Math.pow(10, -6);
    private static final int CPUTIME = 30;
    private static final int PERCENT = 100;
    private static final int FAULTLENGTH = 10;
    static double[] c0;
    static double[] c1;
    public static double CPU=0.0;
    public static boolean flag=false;
    static List<Double> nums=new ArrayList<Double>();
    public static double avg=0;
    static double amount=0;
    static int i=0;
    static String procCmd=System
                    .getenv("windir") + "\\system32\\wbem\\wmic.exe process get Caption,CommandLine,KernelModeTime,ReadOperationCount,"
                            + "ThreadCount,UserModeTime,WriteOperationCount"; 
    static ThreadCPUstart  mt=new ThreadCPUstart();
    static ThreadCPUstop ms=new ThreadCPUstop();
    static ThreadMemory mm=new ThreadMemory();
    public static void ThreadStart() {
        ThreadCPUstart  mt=new ThreadCPUstart();
        mt.start();
    }
    public static void ThreadStop() {
        ThreadCPUstop ms=new ThreadCPUstop();
        ms.start();
    }
   public static class ThreadMemory extends Thread{
       public void run() {
           try {
               while(true) {
                   Thread.sleep(2000);
                   amount=GetMemory.getMemoryRate()+amount;
                   i++;
               }
           }catch(Exception e) {e.printStackTrace();}
       }
   }
    // 以下部分属于详细信息部分
    public static class ThreadCPUstart extends Thread{
        public void run() {
            try {
                // 取进程信息
                synchronized (mt) {
                        getCpuRatioForWindowsBeforeRun();
                        mt.wait();
                        avg=GetMemory.getMemoryRate();
                        getCpuRatioForWindowsAfterRun();
                        mt.stop();
                        ms.stop();
                }
            } catch (Exception e) {
                System.out.println("cannot load monitor info: cpu ratio in windows"+e);
            }
            }
        }
    public static class ThreadCPUstop extends Thread{
        public void run() {
            try {
                synchronized (mt) {
                    mt.notify();
                }
            }catch(Exception e) {e.printStackTrace();}
        }
    }
    public static void getCpuRatioForWindowsBeforeRun() {
            // 取进程信息
        try {
//            Process pro=Runtime.getRuntime().exec(procCmd);
//            pro.getOutputStream();
            c0 = readCpu(Runtime.getRuntime().exec(procCmd));
        }catch(Exception e) {e.printStackTrace();}
    }
    public static double getCpuRatioForWindowsAfterRun() {
        try {
            c1 = readCpu(Runtime.getRuntime().exec(procCmd));
            if (c0 != null && c0.length > 0 && c1 != null && c1.length > 0) {
                double idletime = c1[0] - c0[0];
                double busytime = c1[1] - c0[1];
                CPU=PERCENT * (busytime) / (busytime + idletime);
                return PERCENT * (busytime) / (busytime + idletime);
            }
        } catch (Exception e) {
            System.out.println("cannot load monitor info2: cpu ratio in windows"+e);
        }
        return 0;
    }
    public static double[] readCpu(Process proc) {
        double[] retn = new double[2];
        try (InputStream inputStream = proc.getInputStream()) {
            proc.getOutputStream().close();
            InputStreamReader ir = new InputStreamReader(inputStream);
            LineNumberReader input = new LineNumberReader(ir);
            String line = input.readLine();
            if (line == null || line.length() < FAULTLENGTH) {
                return new double[0];
            }
            int capidx = line.indexOf("Caption");
            int cmdidx = line.indexOf("CommandLine");
            int rocidx = line.indexOf("ReadOperationCount");
            int umtidx = line.indexOf("UserModeTime");
            int kmtidx = line.indexOf("KernelModeTime");
            int wocidx = line.indexOf("WriteOperationCount");
            double idletime = 10;
            double kneltime = 10;
            double usertime = 10;
            while ((line = input.readLine()) != null) {
                if (line.length() < wocidx) {
                    continue;
                }
                // 字段出现顺序:Caption,CommandLine,KernelModeTime,ReadOperationCount,
                // ThreadCount,UserModeTime,WriteOperation
                String caption = line.substring(capidx, cmdidx - 1).trim();
                String cmd = line.substring(cmdidx, kmtidx - 1).trim();
                if (cmd.contains("wmic.exe")) {
                    continue;
                }
                
                String s1 = line.substring(kmtidx, rocidx - 1).trim();
                String s2 = line.substring(umtidx, wocidx - 1).trim();
//                System.out.println("si And s2:" +s1+"::"+s2);
                if(!s1.equals("0        510")) {
                    if (caption.equals("System Idle Process") || caption.equals("System")) {
                    
                    if (s1.length() > 0) {idletime += Long.valueOf(s1);}
                    if (s2.length() > 0) { idletime += Long.valueOf(s2);}
                    continue;
                }
                    if (s1.length() > 0) { kneltime += Long.valueOf(s1);}
                    if (s2.length() > 0) { usertime += Long.valueOf(s2);}
                }
            }
            retn[0] = idletime;
            retn[1] = kneltime + usertime;
            return retn;
        } catch (Exception e) { System.out.println("cannot load monitor info2: read cpu info"+e);}
        return new double[0];
    }
}

获取内存:
1 进程占用的内存概念:
全网最全获取JVM(javaw.exe进程)的CPU占用率

工作集内存:该进程实际再物理内存中的大小。
工作集内存=专用内存+共享内存
所以由定义,本次方案获取的内存为进程的工作集内存。
2 代码操作
通过Java getRuntime方法获取JVM运行环境,得到进程的pid,再通过tasklist的Linux命令获得javaw.exe进程,解析并读取该进程信息工作集内存。
具体流程看详细代码 。

获取内存代码:

public class GetMemory {
    public static String pid=null;
    public static long Memory=0;
    public static boolean ThreadFlag=false;
    static long Average=0;
    static List<Double> nums=new ArrayList<Double>();
    public static double getMemoryRate() {
        long memRate=0;
        memRate=getMemoryRateForWindows();
        return memRate;
    }
    public static  String getJvmPIDOnWindows() {
        RuntimeMXBean runtime=ManagementFactory.getRuntimeMXBean();
        pid=runtime.getName().split("@")[0];
        return pid;
    }
    public static long getMemoryRateForWindows() {
        pid=getJvmPIDOnWindows();
        String command="TASKLIST /NH /FO CSV /FI \"PID EQ "+pid+"\"";
        String remCount="";//jvm??àí?ú′???ó?á?
        String remshare="";
        String remUse="";
        BufferedReader in=null;
        String result="";
        String physicalJvmMem = null;
        String shareJvmMem = null;
        String UseJvmMem = null;
        try {
            Process pro=Runtime.getRuntime().exec(command);
            in=new BufferedReader(new InputStreamReader(pro.getInputStream()));
            StringTokenizer ts=new StringTokenizer(in.readLine(),"\"");
            int i=1;
            while(ts.hasMoreTokens()) {
                i++;
                ts.nextToken();
                if(i==9) {
                    remCount=ts.nextToken().replace(",", "").replace("K", "").trim();
                }
            }
            Memory=Long.parseLong(remCount)/1024;
            in.close();
            pro.destroy();
        }catch(Exception e) {
        }
        return Memory ;
    }
}

相关文章:

  • 2021-05-19
  • 2021-07-29
  • 2021-12-27
  • 2021-10-22
  • 2022-12-23
猜你喜欢
  • 2021-10-12
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-08-25
  • 2022-02-26
  • 2021-12-13
相关资源
相似解决方案