/******************************************************************************* * Copyright 2015 alladin-IT GmbH * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *******************************************************************************/ package at.alladin.rmbt.util.tools; import java.util.ArrayList; import java.util.List; /** * * @author lb * */ public abstract class CpuStat { /** * * @author lb * */ public static class CpuUsage { public static class CoreUsage { int coreNumber; int user; int nice; int system; long idle; int iowait; int irq; int softirq; public CoreUsage(int coreNumber, int user, int nice, int system, long idle, int iowait, int irq, int softirq) { this.coreNumber = coreNumber; this.user = user; this.nice = nice; this.system = system; this.idle = idle; this.iowait = iowait; this.irq = irq; this.softirq = softirq; } public int getCoreNumber() { return coreNumber; } public void setCoreNumber(int coreNumber) { this.coreNumber = coreNumber; } public int getUser() { return user; } public void setUser(int user) { this.user = user; } public int getNice() { return nice; } public void setNice(int nice) { this.nice = nice; } public int getSystem() { return system; } public void setSystem(int system) { this.system = system; } public long getIdle() { return idle; } public void setIdle(long idle) { this.idle = idle; } public int getIowait() { return iowait; } public void setIowait(int iowait) { this.iowait = iowait; } public int getIrq() { return irq; } public void setIrq(int irq) { this.irq = irq; } public int getSoftirq() { return softirq; } public void setSoftirq(int softirq) { this.softirq = softirq; } @Override public String toString() { return "CoreUsage [coreNumber=" + coreNumber + ", user=" + user + ", nice=" + nice + ", system=" + system + ", idle=" + idle + ", iowait=" + iowait + ", irq=" + irq + ", softirq=" + softirq + "]"; } } protected int numCores; protected float[] lastCpuUsage; protected boolean detectedIdleOrIoWaitDrop = false; protected List<CoreUsage> coreUsageList = new ArrayList<>(); public int getNumCores() { return numCores; } public void setNumCores(int numCores) { this.numCores = numCores; } public List<CoreUsage> getCoreUsageList() { return coreUsageList; } public void setCoreUsageList(List<CoreUsage> coreUsageList) { this.coreUsageList = coreUsageList; } public long getIdle(int cpuCore) { return coreUsageList.get(cpuCore).getIdle(); } public long getIoWait(int cpuCore) { return coreUsageList.get(cpuCore).getIowait(); } public long getIoWait() { long ioWait = 0; for (int i = 0; i < coreUsageList.size(); i++) { ioWait += getIoWait(i); } return ioWait; } public long getIdle() { long idle = 0; for (int i = 0; i < coreUsageList.size(); i++) { idle += getIdle(i); } return idle; } public long getCpu(int cpuCore) { long cpu = 0; CoreUsage core = coreUsageList.get(cpuCore); cpu += core.getIowait() + core.getIrq() + core.getNice() + core.getSoftirq() + core.getSystem() + core.getUser(); return cpu; } public long getCpu() { long cpu = 0; for (int i = 0; i < coreUsageList.size(); i++) { cpu += getCpu(i); } return cpu; } /** * needed for arm kernel 3.4 (and maybe more): there is a bug that let the idle and iowait numbers drop sometimes * @param newStat * @return */ private boolean checkForIdleAndIoWaitTimeBug(CpuUsage newStat) { return (getIdle() > newStat.getIdle() || getIoWait() > newStat.getIoWait()); } /** * * @param newStat * @return */ public float[] updateCpuUsage(CpuUsage newStat) { if (checkForIdleAndIoWaitTimeBug(newStat)) { detectedIdleOrIoWaitDrop = true; System.out.println("idle/iowait drop found..."); return getLastCpuUsage(); } float[] result; synchronized (coreUsageList) { final int cores = coreUsageList.size(); final float[] cpu1 = new float[cores]; final float[] cpu2 = new float[cores]; final float[] idle1 = new float[cores]; final float[] idle2 = new float[cores]; result = new float[cores]; try { for (int i = 0; i < coreUsageList.size(); i++) { cpu1[i] = getCpu(i); idle1[i] = getIdle(i); cpu2[i] = newStat.getCpu(i); idle2[i] = newStat.getIdle(i); result[i] = (float)(cpu2[i] - cpu1[i]) / (float)((cpu2[i] + idle2[i]) - (cpu1[i] + idle1[i])); /* * workaround for samsung s4 if the usage is lower than 0% or higher than 100%: * * * first 3 entries are form nexus 4 (correct values): * CpuUsage [numCores=0, coreUsageList=[CoreUsage [coreNumber=0, user=945816, nice=71593, system=672333, idle=44845472, iowait=144684, irq=28, softirq=12832]]] * CpuUsage [numCores=0, coreUsageList=[CoreUsage [coreNumber=0, user=945844, nice=71593, system=672347, idle=44845756, iowait=144684, irq=28, softirq=12832]]] * CpuUsage [numCores=0, coreUsageList=[CoreUsage [coreNumber=0, user=945794, nice=71593, system=672321, idle=44845179, iowait=144684, irq=28, softirq=12832]]] * * now samsung s4 (look at the idle and usage difference between 1st and 2nd and 2nd and 3rd (this can't be correct): * CpuUsage [numCores=0, coreUsageList=[CoreUsage [coreNumber=0, user=35407, nice=12255, system=28215, idle=104615, iowait=4085, irq=0, softirq=714]]] * CpuUsage [numCores=0, coreUsageList=[CoreUsage [coreNumber=0, user=35415, nice=12255, system=28240, idle=104510, iowait=4085, irq=0, softirq=714]]] * CpuUsage [numCores=0, coreUsageList=[CoreUsage [coreNumber=0, user=35428, nice=12255, system=28271, idle=104669, iowait=4087, irq=0, softirq=714]]] */ if (Float.isNaN(result[i]) || result[i] < 0f) { result[i] = 0f; } else if (result[i] > 1f) { result[i] = 1f; } } } catch (IndexOutOfBoundsException e) { e.printStackTrace(); } this.coreUsageList.clear(); this.coreUsageList.addAll(newStat.getCoreUsageList()); this.numCores = cores; } lastCpuUsage = result; return result; } public boolean isDetectedIdleOrIoWaitDrop() { return detectedIdleOrIoWaitDrop; } public float[] getLastCpuUsage() { return lastCpuUsage; } @Override public String toString() { return "CpuUsage [numCores=" + numCores + ", coreUsageList=" + coreUsageList + "]"; } } protected CpuUsage currentCpuUsage; /** * * @return */ public CpuUsage getLastCpuUsage() { return currentCpuUsage; } /** * * @return */ protected abstract CpuUsage getCurrentCpuUsage(boolean getByCore); /** * * @return */ public float[] update(boolean getByCore) { if (currentCpuUsage == null) { currentCpuUsage = getCurrentCpuUsage(getByCore); return null; } else { return currentCpuUsage.updateCpuUsage(getCurrentCpuUsage(getByCore)); } } }