/** * Returns the total time (in milliseconds) spent executing in both user and system code. Safe to * call without lock held. */ public long getCpuTimeForPid(int pid) { synchronized (mSinglePidStatsData) { final String statFile = "/proc/" + pid + "/stat"; final long[] statsData = mSinglePidStatsData; if (Process.readProcFile(statFile, PROCESS_STATS_FORMAT, null, statsData, null)) { long time = statsData[PROCESS_STAT_UTIME] + statsData[PROCESS_STAT_STIME]; return time * mJiffyMillis; } return 0; } }
private int[] collectStats( String statsFile, int parentPid, boolean first, int[] curPids, ArrayList<Stats> allProcs) { int[] pids = Process.getPids(statsFile, curPids); int NP = (pids == null) ? 0 : pids.length; int NS = allProcs.size(); int curStatsIndex = 0; for (int i = 0; i < NP; i++) { int pid = pids[i]; if (pid < 0) { NP = pid; break; } Stats st = curStatsIndex < NS ? allProcs.get(curStatsIndex) : null; if (st != null && st.pid == pid) { // Update an existing process... st.added = false; st.working = false; curStatsIndex++; if (DEBUG) Slog.v( TAG, "Existing " + (parentPid < 0 ? "process" : "thread") + " pid " + pid + ": " + st); if (st.interesting) { final long uptime = SystemClock.uptimeMillis(); final long[] procStats = mProcessStatsData; if (!Process.readProcFile( st.statFile.toString(), PROCESS_STATS_FORMAT, null, procStats, null)) { continue; } final long minfaults = procStats[PROCESS_STAT_MINOR_FAULTS]; final long majfaults = procStats[PROCESS_STAT_MAJOR_FAULTS]; final long utime = procStats[PROCESS_STAT_UTIME] * mJiffyMillis; final long stime = procStats[PROCESS_STAT_STIME] * mJiffyMillis; if (utime == st.base_utime && stime == st.base_stime) { st.rel_utime = 0; st.rel_stime = 0; st.rel_minfaults = 0; st.rel_majfaults = 0; if (st.active) { st.active = false; } continue; } if (!st.active) { st.active = true; } if (parentPid < 0) { getName(st, st.cmdlineFile); if (st.threadStats != null) { mCurThreadPids = collectStats(st.threadsDir, pid, false, mCurThreadPids, st.threadStats); } } if (DEBUG) Slog.v( "Load", "Stats changed " + st.name + " pid=" + st.pid + " utime=" + utime + "-" + st.base_utime + " stime=" + stime + "-" + st.base_stime + " minfaults=" + minfaults + "-" + st.base_minfaults + " majfaults=" + majfaults + "-" + st.base_majfaults); st.rel_uptime = uptime - st.base_uptime; st.base_uptime = uptime; st.rel_utime = (int) (utime - st.base_utime); st.rel_stime = (int) (stime - st.base_stime); st.base_utime = utime; st.base_stime = stime; st.rel_minfaults = (int) (minfaults - st.base_minfaults); st.rel_majfaults = (int) (majfaults - st.base_majfaults); st.base_minfaults = minfaults; st.base_majfaults = majfaults; st.working = true; } continue; } if (st == null || st.pid > pid) { // We have a new process! st = new Stats(pid, parentPid, mIncludeThreads); allProcs.add(curStatsIndex, st); curStatsIndex++; NS++; if (DEBUG) Slog.v(TAG, "New " + (parentPid < 0 ? "process" : "thread") + " pid " + pid + ": " + st); final String[] procStatsString = mProcessFullStatsStringData; final long[] procStats = mProcessFullStatsData; st.base_uptime = SystemClock.uptimeMillis(); String path = st.statFile.toString(); // Slog.d(TAG, "Reading proc file: " + path); if (Process.readProcFile( path, PROCESS_FULL_STATS_FORMAT, procStatsString, procStats, null)) { // This is a possible way to filter out processes that // are actually kernel threads... do we want to? Some // of them do use CPU, but there can be a *lot* that are // not doing anything. st.vsize = procStats[PROCESS_FULL_STAT_VSIZE]; if (true || procStats[PROCESS_FULL_STAT_VSIZE] != 0) { st.interesting = true; st.baseName = procStatsString[0]; st.base_minfaults = procStats[PROCESS_FULL_STAT_MINOR_FAULTS]; st.base_majfaults = procStats[PROCESS_FULL_STAT_MAJOR_FAULTS]; st.base_utime = procStats[PROCESS_FULL_STAT_UTIME] * mJiffyMillis; st.base_stime = procStats[PROCESS_FULL_STAT_STIME] * mJiffyMillis; } else { Slog.i(TAG, "Skipping kernel process pid " + pid + " name " + procStatsString[0]); st.baseName = procStatsString[0]; } } else { Slog.w(TAG, "Skipping unknown process pid " + pid); st.baseName = "<unknown>"; st.base_utime = st.base_stime = 0; st.base_minfaults = st.base_majfaults = 0; } if (parentPid < 0) { getName(st, st.cmdlineFile); if (st.threadStats != null) { mCurThreadPids = collectStats(st.threadsDir, pid, true, mCurThreadPids, st.threadStats); } } else if (st.interesting) { st.name = st.baseName; st.nameWidth = onMeasureProcessName(st.name); } if (DEBUG) Slog.v( "Load", "Stats added " + st.name + " pid=" + st.pid + " utime=" + st.base_utime + " stime=" + st.base_stime + " minfaults=" + st.base_minfaults + " majfaults=" + st.base_majfaults); st.rel_utime = 0; st.rel_stime = 0; st.rel_minfaults = 0; st.rel_majfaults = 0; st.added = true; if (!first && st.interesting) { st.working = true; } continue; } // This process has gone away! st.rel_utime = 0; st.rel_stime = 0; st.rel_minfaults = 0; st.rel_majfaults = 0; st.removed = true; st.working = true; allProcs.remove(curStatsIndex); NS--; if (DEBUG) Slog.v( TAG, "Removed " + (parentPid < 0 ? "process" : "thread") + " pid " + pid + ": " + st); // Decrement the loop counter so that we process the current pid // again the next time through the loop. i--; continue; } while (curStatsIndex < NS) { // This process has gone away! final Stats st = allProcs.get(curStatsIndex); st.rel_utime = 0; st.rel_stime = 0; st.rel_minfaults = 0; st.rel_majfaults = 0; st.removed = true; st.working = true; allProcs.remove(curStatsIndex); NS--; if (localLOGV) Slog.v(TAG, "Removed pid " + st.pid + ": " + st); } return pids; }
public void update() { if (DEBUG) Slog.v(TAG, "Update: " + this); final long nowUptime = SystemClock.uptimeMillis(); final long nowRealtime = SystemClock.elapsedRealtime(); final long nowWallTime = System.currentTimeMillis(); final long[] sysCpu = mSystemCpuData; if (Process.readProcFile("/proc/stat", SYSTEM_CPU_FORMAT, null, sysCpu, null)) { // Total user time is user + nice time. final long usertime = (sysCpu[0] + sysCpu[1]) * mJiffyMillis; // Total system time is simply system time. final long systemtime = sysCpu[2] * mJiffyMillis; // Total idle time is simply idle time. final long idletime = sysCpu[3] * mJiffyMillis; // Total irq time is iowait + irq + softirq time. final long iowaittime = sysCpu[4] * mJiffyMillis; final long irqtime = sysCpu[5] * mJiffyMillis; final long softirqtime = sysCpu[6] * mJiffyMillis; // This code is trying to avoid issues with idle time going backwards, // but currently it gets into situations where it triggers most of the time. :( if (true || (usertime >= mBaseUserTime && systemtime >= mBaseSystemTime && iowaittime >= mBaseIoWaitTime && irqtime >= mBaseIrqTime && softirqtime >= mBaseSoftIrqTime && idletime >= mBaseIdleTime)) { mRelUserTime = (int) (usertime - mBaseUserTime); mRelSystemTime = (int) (systemtime - mBaseSystemTime); mRelIoWaitTime = (int) (iowaittime - mBaseIoWaitTime); mRelIrqTime = (int) (irqtime - mBaseIrqTime); mRelSoftIrqTime = (int) (softirqtime - mBaseSoftIrqTime); mRelIdleTime = (int) (idletime - mBaseIdleTime); mRelStatsAreGood = true; if (DEBUG) { Slog.i( "Load", "Total U:" + (sysCpu[0] * mJiffyMillis) + " N:" + (sysCpu[1] * mJiffyMillis) + " S:" + (sysCpu[2] * mJiffyMillis) + " I:" + (sysCpu[3] * mJiffyMillis) + " W:" + (sysCpu[4] * mJiffyMillis) + " Q:" + (sysCpu[5] * mJiffyMillis) + " O:" + (sysCpu[6] * mJiffyMillis)); Slog.i( "Load", "Rel U:" + mRelUserTime + " S:" + mRelSystemTime + " I:" + mRelIdleTime + " Q:" + mRelIrqTime); } mBaseUserTime = usertime; mBaseSystemTime = systemtime; mBaseIoWaitTime = iowaittime; mBaseIrqTime = irqtime; mBaseSoftIrqTime = softirqtime; mBaseIdleTime = idletime; } else { mRelUserTime = 0; mRelSystemTime = 0; mRelIoWaitTime = 0; mRelIrqTime = 0; mRelSoftIrqTime = 0; mRelIdleTime = 0; mRelStatsAreGood = false; Slog.w(TAG, "/proc/stats has gone backwards; skipping CPU update"); return; } } mLastSampleTime = mCurrentSampleTime; mCurrentSampleTime = nowUptime; mLastSampleRealTime = mCurrentSampleRealTime; mCurrentSampleRealTime = nowRealtime; mLastSampleWallTime = mCurrentSampleWallTime; mCurrentSampleWallTime = nowWallTime; final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads(); try { mCurPids = collectStats("/proc", -1, mFirst, mCurPids, mProcStats); } finally { StrictMode.setThreadPolicy(savedPolicy); } final float[] loadAverages = mLoadAverageData; if (Process.readProcFile("/proc/loadavg", LOAD_AVERAGE_FORMAT, null, null, loadAverages)) { float load1 = loadAverages[0]; float load5 = loadAverages[1]; float load15 = loadAverages[2]; if (load1 != mLoad1 || load5 != mLoad5 || load15 != mLoad15) { mLoad1 = load1; mLoad5 = load5; mLoad15 = load15; onLoadChanged(load1, load5, load15); } } if (DEBUG) Slog.i( TAG, "*** TIME TO COLLECT STATS: " + (SystemClock.uptimeMillis() - mCurrentSampleTime)); mWorkingProcsSorted = false; mFirst = false; }