CPU利用率的计算

博客内容探讨了如何通过uptime命令的输出计算CPU利用率,强调利用第一个数值与第二个数值的差值来估算CPU空闲时间的比例,从而得到CPU的使用率。此外,还提及了获取每个CPU单独利用率的代码方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

proc/stat文件有实时CPU信息:
第一行的数值表示CPU总的使用情况,这些数据都是以clock_tick为单位记录的,这里的clock_tick在绝大多数机器上是10ms。
cpu  273732 21735 288867 3822516 5883 3 5724 0 0 0
解读:
user(273732):从系统启动开始累计到当前时刻,统计CPU执行高优先级用户程序的时间(nice <= 0)。
nice(21735):从系统启动开始累计到当前时刻,统计CPU执行低优先级用户程序的时间(nice > 0)。
system(288867):从系统启动开始累计到当前时刻,CPU处于核心态的时间。
idle(3822516):从系统启动开始累计到当前时刻,系统处于idle进程的时间,Linux提供一种特殊的进程称为idle进程,其pid为0。
iowait(5883):从系统启动开始累计到当前时刻,IO等待时间。
irq(3):从系统启动开始累计到当前时刻,硬中断时间。
softirq(5724):从系统启动开始累计到当前时刻,软中断时间。
steal(0):窃取的时间,虚拟环境被其他操作系统窃取的CPU时间。
guest(0):在内核控制下虚拟出来的CPU访问客户操作系统的时间。
guest_nice(0):Time spent running a niced guest (virtual CPU for guest operating systems under the control of the Linux kernel)

我们日常所关心的CPU性能主要是CPU的利用率,即处于繁忙阶段的时间片占总cpu时间片的比值。基本的计算思想:在尽可能小的时间间隔内取两个cpu的时间状态,
包括处于繁忙的时间片和处于非空闲的时间片,作商即可。


方法1:借助/proc/stat文件。

即取两个尽可能短的时间间隔内的cpu统计数据分别为:

Total1=User1+nice1+system1+idle1+iowait1+irq1+softirq1+steal1+guest1+guest_nice1

Total2=User2+nice2+system2+idle2+iowait2+irq2+softirq2+steal2+guest2+guest_nice2

则CPU-usage=((total2-idle2)-(total1-idle1))/(total2-total1)


方法2:较为简单,这直接用/proc/uptime

尽管uptime仅有两个数值,但是表示总时间和CPU为idle的时间,已足以计算CPU的利用率,即delta(第一个数值-第二个数值)/delta(第一个数值)

求各CPU单独的利用率的代码:

public class CpuUseInfo {
    String cpuName = "cpu";
    /**
     * CPU执行高优先级用户程序的时间
     */
    long user = 0L;
    /**
     * CPU执行低优先级用户程序的时间
     */
    long nice = 0L;
    /**
     * CPU处于核心态的时间
     */
    long system = 0L;
    /**
     * CPU处于空闲的时间
     */
    long idle = 0L;
    /**
     * io等待时间
     */
    long iowait = 0L;
    /**
     * 硬中断时间
     */
    long irq = 0L;
    /**
     * 软中断时间
     */
    long softirq = 0L;
    /**
     * 当前频率值 scaling_cur_freq / cpuinfo_cur_freq
     */
    int curFrq = 0;

    public CpuUseInfo(int paramInt) {
        if (paramInt >= 0) {
            this.cpuName = ("cpu" + String.valueOf(paramInt)); // cpu0--cpu7的字符串
        }
    }

    @Override
    public String toString() {
        return "zyf cpuName: " + cpuName + ", user: " + user + ", nice: "
                + nice + ", system: " + system + ", idle: " + idle
                + ", iowait: " + iowait + ", irq: " + irq + ", softirq: "
                + softirq + ", curFrq: " + curFrq;
    }

}

public class MainActivity extends Activity {

    private Button mBtn;
    private CpuUseInfo[] mLastAg;
    private CpuUseInfo[] mCurrentAg;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mBtn = (Button) findViewById(R.id.btn);

        mBtn.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                if (mLastAg == null) {
                    mLastAg = e();
                } else {
                    mCurrentAg = e();
                    CpuUseInfo[] deltaInfo = delta(mLastAg, mCurrentAg);
                    if (deltaInfo != null) {
                        for (int i = 0; i < deltaInfo.length; i++) {
                            long total = deltaInfo[i].user + deltaInfo[i].nice
                                    + deltaInfo[i].system + deltaInfo[i].idle
                                    + deltaInfo[i].iowait + deltaInfo[i].irq
                                    + deltaInfo[i].softirq;
                            if (total != 0) {
                                System.out.println("zyf " + deltaInfo[i].cpuName + " 的利用率是: "
                                                + ((int) (100 * (total - deltaInfo[i].idle)) / total) + " %");
                            } else {
                                System.out.println("zyf " + deltaInfo[i].cpuName + " 的利用率是: 0");
                            }
                        }
                    }
                    mLastAg = mCurrentAg;
                }
            }
        });

    }

    private CpuUseInfo[] delta(CpuUseInfo[] lastInfo, CpuUseInfo[] currentInfo) {
        CpuUseInfo[] cpuUseInfo = null;
        if (lastInfo.length == currentInfo.length) {
            cpuUseInfo = new CpuUseInfo[lastInfo.length];
            for (int i = 0; i < lastInfo.length; i++) {
                cpuUseInfo[i] = new CpuUseInfo(i);
                cpuUseInfo[i].cpuName = lastInfo[i].cpuName;
                cpuUseInfo[i].user = Math.abs(currentInfo[i].user
                        - lastInfo[i].user);
                cpuUseInfo[i].nice = Math.abs(currentInfo[i].nice
                        - lastInfo[i].nice);
                cpuUseInfo[i].system = Math.abs(currentInfo[i].system
                        - lastInfo[i].system);
                cpuUseInfo[i].idle = Math.abs(currentInfo[i].idle
                        - lastInfo[i].idle);
                cpuUseInfo[i].iowait = Math.abs(currentInfo[i].iowait
                        - lastInfo[i].iowait);
                cpuUseInfo[i].irq = Math.abs(currentInfo[i].irq
                        - lastInfo[i].irq);
                cpuUseInfo[i].softirq = Math.abs(currentInfo[i].softirq
                        - lastInfo[i].softirq);
            }
        }
        return cpuUseInfo;
    }

    private CpuUseInfo[] e() {
        int count = Runtime.getRuntime().availableProcessors();
        CpuUseInfo[] infos = new CpuUseInfo[count];
        BufferedReader localBufferedReader = null;
        try {
            localBufferedReader = new BufferedReader(new FileReader(
                    "/proc/stat"));
            // 读取CPU总信息,不做处理,为了方便下面统计个CPU的数据
            localBufferedReader.readLine();
        } catch (Exception e) {
            e.printStackTrace();
        }
        String str = null;
        String cpuName;
        for (int i = 0; i < infos.length; i++) {
            try {
                str = localBufferedReader.readLine();
            } catch (Exception e1) {
                e1.printStackTrace();
            }
            if (str != null && str.startsWith("cpu")) {
                // System.out.println("zyf /proc/stat readLine cpu: " + str);
                StringTokenizer st = new StringTokenizer(str);
                cpuName = st.nextToken();
                if (cpuName.length() > 3) {
                    int cpuIndex = Integer.parseInt(cpuName.substring(3), 10); // 转换为十进制
                    if (infos[cpuIndex] == null) {
                        infos[cpuIndex] = new CpuUseInfo(cpuIndex);
                    }
                    infos[cpuIndex].cpuName = cpuName;
                    infos[cpuIndex].user = Long.parseLong(st.nextToken(), 10);
                    infos[cpuIndex].nice = Long.parseLong(st.nextToken(), 10);
                    infos[cpuIndex].system = Long.parseLong(st.nextToken(), 10);
                    infos[cpuIndex].idle = Long.parseLong(st.nextToken(), 10);
                    infos[cpuIndex].iowait = Long.parseLong(st.nextToken(), 10);
                    infos[cpuIndex].irq = Long.parseLong(st.nextToken(), 10);
                    infos[cpuIndex].softirq = Long
                            .parseLong(st.nextToken(), 10);

                    infos[cpuIndex].curFrq = readFile(
                            String.format("/sys/devices/system/cpu/%s/cpufreq/scaling_cur_freq", cpuName), 0);
                    if (infos[cpuIndex].curFrq == 0) {
                        infos[cpuIndex].curFrq = readFile(
                                String.format("/sys/devices/system/cpu/%s/cpufreq/cpuinfo_cur_freq", cpuName), 0);
                    }
                    // System.out.println(arrayOfag[cpuIndex].toString());
                }
            }
            if (infos[i] == null) {
                infos[i] = new CpuUseInfo(i);
            }
            // System.out.println(arrayOfag[i].toString());
        }
        try {
            localBufferedReader.close();
        } catch (IOException e1) {
            e1.printStackTrace();
        }

        return infos;
    }

    private int readFile(String path, int defaultValue) {
        try {
            BufferedReader bufferedReader = new BufferedReader(new FileReader(
                    path));
            int i = Integer.parseInt(bufferedReader.readLine(), 10);
            bufferedReader.close();
            return i;
        } catch (Exception localException) {
        }
        return defaultValue;
    }

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值