FileDocCategorySizeDatePackage
ProcessStats.javaAPI DocAndroid 1.5 API20200Wed May 06 22:42:00 BST 2009com.android.server

ProcessStats

public class ProcessStats extends Object

Fields Summary
private static final String
TAG
private static final boolean
DEBUG
private static final boolean
localLOGV
private static final int[]
PROCESS_STATS_FORMAT
private final long[]
mProcessStatsData
private static final int[]
PROCESS_FULL_STATS_FORMAT
private final String[]
mProcessFullStatsStringData
private final long[]
mProcessFullStatsData
private static final int[]
SYSTEM_CPU_FORMAT
private final long[]
mSystemCpuData
private static final int[]
LOAD_AVERAGE_FORMAT
private final float[]
mLoadAverageData
private final boolean
mIncludeThreads
private float
mLoad1
private float
mLoad5
private float
mLoad15
private long
mCurrentSampleTime
private long
mLastSampleTime
private long
mBaseUserTime
private long
mBaseSystemTime
private long
mBaseIoWaitTime
private long
mBaseIrqTime
private long
mBaseSoftIrqTime
private long
mBaseIdleTime
private int
mRelUserTime
private int
mRelSystemTime
private int
mRelIoWaitTime
private int
mRelIrqTime
private int
mRelSoftIrqTime
private int
mRelIdleTime
private int[]
mCurPids
private int[]
mCurThreadPids
private final ArrayList
mProcStats
private final ArrayList
mWorkingProcs
private boolean
mWorkingProcsSorted
private boolean
mFirst
private byte[]
mBuffer
private static final Comparator
sLoadComparator
Constructors Summary
public ProcessStats(boolean includeThreads)



       
        mIncludeThreads = includeThreads;
    
Methods Summary
private int[]collectStats(java.lang.String statsFile, int parentPid, boolean first, int[] curPids, java.util.ArrayList allProcs, java.util.ArrayList workingProcs)

        
        workingProcs.clear();

        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;
                curStatsIndex++;
                if (localLOGV) Log.v(TAG, "Existing pid " + pid + ": " + st);

                final long[] procStats = mProcessStatsData;
                if (!Process.readProcFile(st.statFile.toString(),
                        PROCESS_STATS_FORMAT, null, procStats, null)) {
                    continue;
                }
                
                final long utime = procStats[0];
                final long stime = procStats[1];

                if (utime == st.base_utime && stime == st.base_stime) {
                    st.rel_utime = 0;
                    st.rel_stime = 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,
                                st.workingThreads);
                    }
                }

                st.rel_utime = (int)(utime - st.base_utime);
                st.rel_stime = (int)(stime - st.base_stime);
                st.base_utime = utime;
                st.base_stime = stime;
                //Log.i("Load", "Stats changed " + name + " pid=" + st.pid
                //      + " name=" + st.name + " utime=" + utime
                //      + " stime=" + stime);
                workingProcs.add(st);
                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 (localLOGV) Log.v(TAG, "New pid " + pid + ": " + st);

                final String[] procStatsString = mProcessFullStatsStringData;
                final long[] procStats = mProcessFullStatsData;
                if (Process.readProcFile(st.statFile.toString(),
                        PROCESS_FULL_STATS_FORMAT, procStatsString,
                        procStats, null)) {
                    st.baseName = parentPid < 0
                            ? procStatsString[0] : Integer.toString(pid);
                    st.base_utime = procStats[1];
                    st.base_stime = procStats[2];
                } else {
                    st.baseName = "<unknown>";
                    st.base_utime = st.base_stime = 0;
                }

                if (parentPid < 0) {
                    getName(st, st.cmdlineFile);
                } else {
                    st.name = st.baseName;
                    st.nameWidth = onMeasureProcessName(st.name);
                    if (st.threadStats != null) {
                        mCurThreadPids = collectStats(st.threadsDir, pid, true,
                                mCurThreadPids, st.threadStats,
                                st.workingThreads);
                    }
                }
                
                //Log.i("Load", "New process: " + st.pid + " " + st.name);
                st.rel_utime = 0;
                st.rel_stime = 0;
                st.added = true;
                if (!first) {
                    workingProcs.add(st);
                }
                continue;
            }
                
            // This process has gone away!
            st.rel_utime = 0;
            st.rel_stime = 0;
            st.removed = true;
            workingProcs.add(st);
            allProcs.remove(curStatsIndex);
            NS--;
            if (localLOGV) Log.v(TAG, "Removed pid " + st.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.removed = true;
            workingProcs.add(st);
            allProcs.remove(curStatsIndex);
            NS--;
            if (localLOGV) Log.v(TAG, "Removed pid " + st.pid + ": " + st);
        }
        
        return pids;
    
public final intcountWorkingStats()

        if (!mWorkingProcsSorted) {
            Collections.sort(mWorkingProcs, sLoadComparator);
            mWorkingProcsSorted = true;
        }
        return mWorkingProcs.size();
    
public final intgetLastIdleTime()

        return mRelIdleTime;
    
public final intgetLastIoWaitTime()

        return mRelIoWaitTime;
    
public final intgetLastIrqTime()

        return mRelIrqTime;
    
public final intgetLastSoftIrqTime()

        return mRelSoftIrqTime;
    
public final intgetLastSystemTime()

        return mRelSystemTime;
    
public final intgetLastUserTime()

        return mRelUserTime;
    
private voidgetName(com.android.server.ProcessStats$Stats st, java.lang.String cmdlineFile)

        String newName = st.baseName;
        if (st.baseName == null || st.baseName.equals("app_process")) {
            String cmdName = readFile(cmdlineFile, '\0");
            if (cmdName != null && cmdName.length() > 1) {
                newName = cmdName;
                int i = newName.lastIndexOf("/");
                if (i > 0 && i < newName.length()-1) {
                    newName = newName.substring(i+1);
                }
            }
        }
        if (st.name == null || !newName.equals(st.name)) {
            st.name = newName;
            st.nameWidth = onMeasureProcessName(st.name);
        }
    
public final floatgetTotalCpuPercent()

        return ((float)(mRelUserTime+mRelSystemTime+mRelIrqTime)*100)
                / (mRelUserTime+mRelSystemTime+mRelIrqTime+mRelIdleTime);
    
public final com.android.server.ProcessStats$StatsgetWorkingStats(int index)

        return mWorkingProcs.get(index);
    
public voidinit()

        mFirst = true;
        update();
    
public voidonLoadChanged(float load1, float load5, float load15)

    
public intonMeasureProcessName(java.lang.String name)

        return 0;
    
public final java.lang.StringprintCurrentState()

        if (!mWorkingProcsSorted) {
            Collections.sort(mWorkingProcs, sLoadComparator);
            mWorkingProcsSorted = true;
        }
        
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        pw.print("Load: ");
        pw.print(mLoad1);
        pw.print(" / ");
        pw.print(mLoad5);
        pw.print(" / ");
        pw.println(mLoad15);
        
        long now = SystemClock.uptimeMillis();
        
        pw.print("CPU usage from ");
        pw.print(now-mLastSampleTime);
        pw.print("ms to ");
        pw.print(now-mCurrentSampleTime);
        pw.println("ms ago:");
        
        final int totalTime = mRelUserTime + mRelSystemTime + mRelIoWaitTime + mRelIrqTime + 
                mRelSoftIrqTime + mRelIdleTime;
        
        int N = mWorkingProcs.size();
        for (int i=0; i<N; i++) {
            Stats st = mWorkingProcs.get(i);
            printProcessCPU(pw, st.added ? " +" : (st.removed ? " -": "  "),
                    st.name, totalTime, st.rel_utime, st.rel_stime, 0, 0, 0);
            if (!st.removed && st.workingThreads != null) {
                int M = st.workingThreads.size();
                for (int j=0; j<M; j++) {
                    Stats tst = st.workingThreads.get(j);
                    printProcessCPU(pw,
                            tst.added ? "   +" : (tst.removed ? "   -": "    "),
                            tst.name, totalTime, tst.rel_utime, tst.rel_stime, 0, 0, 0);
                }
            }
        }
        
        printProcessCPU(pw, "", "TOTAL", totalTime, mRelUserTime, mRelSystemTime, mRelIoWaitTime,
                mRelIrqTime, mRelSoftIrqTime);
        
        return sw.toString();
    
private voidprintProcessCPU(java.io.PrintWriter pw, java.lang.String prefix, java.lang.String label, int totalTime, int user, int system, int iowait, int irq, int softIrq)

        pw.print(prefix);
        pw.print(label);
        pw.print(": ");
        if (totalTime == 0) totalTime = 1;
        pw.print(((user+system+iowait+irq+softIrq)*100)/totalTime);
        pw.print("% = ");
        pw.print((user*100)/totalTime);
        pw.print("% user + ");
        pw.print((system*100)/totalTime);
        pw.print("% kernel");
        if (iowait > 0) {
            pw.print(" + ");
            pw.print((iowait*100)/totalTime);
            pw.print("% iowait");
        }
        if (irq > 0) {
            pw.print(" + ");
            pw.print((irq*100)/totalTime);
            pw.print("% irq");
        }
        if (softIrq > 0) {
            pw.print(" + ");
            pw.print((softIrq*100)/totalTime);
            pw.print("% softirq");
        }
        pw.println();
    
private java.lang.StringreadFile(java.lang.String file, char endChar)

        try {
            FileInputStream is = new FileInputStream(file);
            int len = is.read(mBuffer);
            is.close();

            if (len > 0) {
                int i;
                for (i=0; i<len; i++) {
                    if (mBuffer[i] == endChar) {
                        break;
                    }
                }
                return new String(mBuffer, 0, 0, i);
            }
        } catch (java.io.FileNotFoundException e) {
        } catch (java.io.IOException e) {
        }
        return null;
    
public voidupdate()

        mLastSampleTime = mCurrentSampleTime;
        mCurrentSampleTime = SystemClock.uptimeMillis();
        
        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);
            }
        }

        mCurPids = collectStats("/proc", -1, mFirst, mCurPids,
                mProcStats, mWorkingProcs);
        mFirst = false;
        
        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];
            // Total system time is simply system time.
            final long systemtime = sysCpu[2];
            // Total idle time is simply idle time.
            final long idletime = sysCpu[3];
            // Total irq time is iowait + irq + softirq time.
            final long iowaittime = sysCpu[4];
            final long irqtime = sysCpu[5];
            final long softirqtime = sysCpu[6];

            mRelUserTime = (int)(usertime - mBaseUserTime);
            mRelSystemTime = (int)(systemtime - mBaseSystemTime);
            mRelIoWaitTime = (int)(iowaittime - mBaseIoWaitTime);
            mRelIrqTime = (int)(irqtime - mBaseIrqTime);
            mRelSoftIrqTime = (int)(softirqtime - mBaseSoftIrqTime);
            mRelIdleTime = (int)(idletime - mBaseIdleTime);

            if (false) {
                Log.i("Load", "Total U:" + sysCpu[0] + " N:" + sysCpu[1]
                      + " S:" + sysCpu[2] + " I:" + sysCpu[3]
                      + " W:" + sysCpu[4] + " Q:" + sysCpu[5]
                      + " O:" + sysCpu[6]);
                Log.i("Load", "Rel U:" + mRelUserTime + " S:" + mRelSystemTime
                      + " I:" + mRelIdleTime + " Q:" + mRelIrqTime);
            }

            mBaseUserTime = usertime;
            mBaseSystemTime = systemtime;
            mBaseIoWaitTime = iowaittime;
            mBaseIrqTime = irqtime;
            mBaseSoftIrqTime = softirqtime;
            mBaseIdleTime = idletime;
        }

        mWorkingProcsSorted = false;
        mFirst = false;