Android 基礎性能數據獲取(/proc/)

一、系統內存

讀取命令:

/proc/meminfo

Java代碼:

	private void click(){
        try{
            String cmd = "/proc/meminfo";
            BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(cmd)), 1000);
            StringBuilder sb = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null){
                sb.append(line).append("\n");
            }
            Log.e("/proc/meminfo : " + sb.toString());
            reader.close();
        }catch (Exception ex){
            ex.printStackTrace();
            Log.e("click [/proc/meminfo] exception : " + ex.toString());
        }
    }

輸出結果:

	MemTotal:        5859784 kB
    MemFree:          394708 kB
    MemAvailable:    2660552 kB
    Buffers:            4640 kB
    Cached:          2209396 kB
    SwapCached:        58852 kB
    Active:          2008348 kB
    Inactive:        1365356 kB
    Active(anon):     897500 kB
    Inactive(anon):   350412 kB
    Active(file):    1110848 kB
    Inactive(file):  1014944 kB
    Unevictable:       67908 kB
    Mlocked:           67908 kB
    SwapTotal:       2293756 kB
    SwapFree:        1555948 kB
    Dirty:               480 kB
    Writeback:             0 kB
    AnonPages:       1207652 kB
    Mapped:           476364 kB
    Shmem:             22764 kB
    Slab:             339180 kB
    SReclaimable:     119880 kB
    SUnreclaim:       219300 kB
    KernelStack:       55888 kB
    PageTables:        76060 kB
    NFS_Unstable:          0 kB
    Bounce:                0 kB
    WritebackTmp:          0 kB
    CommitLimit:     5223648 kB
    Committed_AS:   99107264 kB
    VmallocTotal:   263061440 kB
    VmallocUsed:           0 kB
    VmallocChunk:          0 kB
    CmaTotal:         917504 kB
    CmaFree:           34788 kB
    IonTotalCache:    165936 kB
    IonTotalUsed:     195136 kB
    PActive(anon):         0 kB
    PInactive(anon):       0 kB
    PActive(file):         0 kB
    PInactive(file):       0 kB
    Isolate1Free:       6276 kB
    Isolate2Free:       5568 kB
    RsvTotalUsed:     276484 kB

字段含義說明:

	MemTotal:       所有可用RAM大小。
    MemFree:        LowFree與HighFree的總和,被系統留着未使用的內存。
    Buffers:        用來給文件做緩衝大小。
    Cached:         被高速緩衝存儲器(cache memory)用的內存的大小(等於diskcache minus SwapCache)。
    SwapCached:     被高速緩衝存儲器(cache memory)用的交換空間的大小。已經被交換出來的內存,仍然被存放在swapfile中,用來在需要的時候很快的被替換而不需要再次打開I/O端口。
    Active:         在活躍使用中的緩衝或高速緩衝存儲器頁面文件的大小,除非非常必要,否則不會被移作他用。
    Inactive:       在不經常使用中的緩衝或高速緩衝存儲器頁面文件的大小,可能被用於其他途徑。
    SwapTotal:      交換空間的總大小。
    SwapFree:       未被使用交換空間的大小。
    Dirty:          等待被寫回到磁盤的內存大小。
    Writeback:      正在被寫回到磁盤的內存大小。
    AnonPages:     未映射頁的內存大小。
    Mapped:         設備和文件等映射的大小。
    Slab:           內核數據結構緩存的大小,可以減少申請和釋放內存帶來的消耗。
    SReclaimable:   可收回Slab的大小。
    SUnreclaim:    不可收回Slab的大小(SUnreclaim+SReclaimable=Slab)。
    PageTables:    管理內存分頁頁面的索引表的大小。
    NFS_Unstable:   不穩定頁表的大小。

系統內存總容量: 只需要讀取“/proc/meminfo”文件的第一個字段“MemTotal”就可以了。

系統空閒的內存: 只需要通過ActivityManager即可獲取。

	//系統空閒內存
    public static long getSysFreeMemory(Context context) {
        ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo();
        am.getMemoryInfo(mi);
        return mi.availMem;
    }

二、進程內存

進程內存上限:

	//進程內存上限
    public static int getMemoryMax() {
        return (int) (Runtime.getRuntime().maxMemory()/1024);
    }

進程總內存:

	//進程總內存
    public static int getPidMemorySize(int pid, Context context) {
        ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        int[] myMempid = new int[] { pid };
        Debug.MemoryInfo[] memoryInfo = am.getProcessMemoryInfo(myMempid);
        int memSize = memoryInfo[0].getTotalPss();
        //        dalvikPrivateDirty: The private dirty pages used by dalvik。
        //        dalvikPss :The proportional set size for dalvik.
        //        dalvikSharedDirty :The shared dirty pages used by dalvik.
        //        nativePrivateDirty :The private dirty pages used by the native heap.
        //        nativePss :The proportional set size for the native heap.
        //        nativeSharedDirty :The shared dirty pages used by the native heap.
        //        otherPrivateDirty :The private dirty pages used by everything else.
        //        otherPss :The proportional set size for everything else.
        //        otherSharedDirty :The shared dirty pages used by everything else.
        return memSize;
    }

GT3.1開源獲取內存數據代碼:
https://github.com/Tencent/GT/blob/ed3a289a897d0ea14676a7c7d92344f5b398991e/android/GT_APP/app/src/main/java/com/tencent/wstt/gt/api/utils/MemUtils.java


三、CPU篇

CPU :表示進程或線程的繁忙程度

獲取CPU主要用兩種方法:

  • 一種是利用top命令或者dumpsys cpuinfo,
  • 第二種是讀取/proc/stat文件,然後解析相關參數,自己去計算。

下面主要介紹第二種方法,也是個人比較推薦的方法

/proc文件系統是一個僞文件系統,它只存在內存當中,而不佔用外存空間。它以文件系統的方式爲內核與進程提供通信的接口。用戶和應用程序可以通過/proc得到系統的信息,並可以改變內核的某些參數。由於系統的信息,如進程,是動態改變的,所以用戶或應用程序讀取/proc目錄中的文件時,proc文件系統是動態從系統內核讀出所需信息並提交的。 從proc文件中可以獲取系統、進程、線程的cpu時間片使用情況,所以兩次採集時間片的數據就可以獲取進程CPU佔用率, CPU佔用率 = (進程T2-進程T1)/(系統T2-系統T1) 的時間片比值。

1、獲取系統CPU時間片

獲取系統CPU時間片使用情況:讀取proc/stat,文件的內容如下:

	cpu 2032004 102648 238344 167130733 758440 15159 17878 0
    cpu0 1022597 63462 141826 83528451 366530 9362 15386 0
    cpu1 1009407 39185 96518 83602282 391909 5796 2492 0
    intr 303194010 212852371 3 0 0 11 0 0 2 1 1 0 0 3 0 11097365 0 72615114 6628960 0 179 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    ctxt 236095529
    btime 1195210746
    processes 401389
    procs_running 1
    procs_blocked 0

第一行各個字段的含義:

	user (14624) 從系統啓動開始累計到當前時刻,處於用戶態的運行時間,不包含 nice值爲負進程。 
    nice (771) 從系統啓動開始累計到當前時刻,nice值爲負的進程所佔用的CPU時間 
    system (8484) 從系統啓動開始累計到當前時刻,處於核心態的運行時間 
    idle (283052) 從系統啓動開始累計到當前時刻,除IO等待時間以外的其它等待時間 
    iowait (0) 從系統啓動開始累計到當前時刻,IO等待時間(since 2.5.41) 
    irq (0) 從系統啓動開始累計到當前時刻,硬中斷時間(since 2.6.0-test4) 
    softirq (62) 從系統啓動開始累計到當前時刻,軟中斷時間(since 2.6.0-test4) 

總的cpu時間totalCpuTime = user + nice + system + idle + iowait + irq + softirq

2、獲取進程和線程的CPU時間片

獲取進程CPU時間片使用情況:讀取proc/pid/stat,獲取線程CPU時間片使用情況:讀取proc/pid/task/tid/stat,這兩個文件的內容相同,如下

6873 (a.out) R 6723 6873 6723 34819 6873 8388608 77 0 0 0 41958 31 0 0 25 0 3 0 5882654 1409024 56 4294967295 134512640 134513720 3215579040 0 2097798 0 0 0 0 0 0 0 17 0 0 0

各個字段的含義:

	pid=6873                  進程(包括輕量級進程,即線程)號
    comm=a.out                應用程序或命令的名字
    task_state=R              任務的狀態,R:runnign, S:sleeping (TASK_INTERRUPTIBLE), D:disk sleep (TASK_UNINTERRUPTIBLE), T: stopped, T:tracing stop,Z:zombie, X:dead
    ppid=6723                 父進程ID
    pgid=6873                 線程組號
    sid=6723                  c該任務所在的會話組ID
    tty_nr=34819(pts/3)       該任務的tty終端的設備號,INT(34817/256=主設備號,(34817-主設備號)=次設備號
    tty_pgrp=6873             終端的進程組號,當前運行在該任務所在終端的前臺任務(包括shell 應用程序)的PID。
    task->flags=8388608       進程標誌位,查看該任務的特性
    min_flt=77                該任務不需要從硬盤拷數據而發生的缺頁(次缺頁)的次數
    cmin_flt=0                累計的該任務的所有的waited-for進程曾經發生的次缺頁的次數目
    maj_flt=0                 該任務需要從硬盤拷數據而發生的缺頁(主缺頁)的次數
    cmaj_flt=0                累計的該任務的所有的waited-for進程曾經發生的主缺頁的次數目
    utime=1587                該任務在用戶態運行的時間,單位爲jiffies
    stime=1                   該任務在覈心態運行的時間,單位爲jiffies
    cutime=0                  累計的該任務的所有的waited-for進程曾經在用戶態運行的時間,單位爲jiffies
    cstime=0                  累計的該任務的所有的waited-for進程曾經在覈心態運行的時間,單位爲jiffies
    priority=25               任務的動態優先級
    nice=0                    任務的靜態優先級
    num_threads=3             該任務所在的線程組裏線程的個數
    it_real_value=0           由於計時間隔導致的下一個 SIGALRM 發送進程的時延,以 jiffy 爲單位.
    start_time=5882654        該任務啓動的時間,單位爲jiffies
    vsize=1409024           (page)該任務的虛擬地址空間大小
    rss=56(page)             該任務當前駐留物理地址空間的大小
    rlim=4294967295(bytes)  該任務能駐留物理地址空間的最大值
    start_code=134512640     該任務在虛擬地址空間的代碼段的起始地址
    end_code=134513720       該任務在虛擬地址空間的代碼段的結束地址
    start_stack=3215579040   該任務在虛擬地址空間的棧的結束地址
    kstkesp=0                esp(32 位堆棧指針) 的當前值, 與在進程的內核堆棧頁得到的一致.
    kstkeip=2097798          指向將要執行的指令的指針, EIP(32 位指令指針)的當前值.
    pendingsig=0             待處理信號的位圖,記錄發送給進程的普通信號
    block_sig=0              阻塞信號的位圖
    sigign=0                 忽略的信號的位圖
    sigcatch=082985          被俘獲的信號的位圖
    wchan=0                  如果該進程是睡眠狀態,該值給出調度的調用點
    nswap                    被swapped的頁數,當前沒用
    cnswap                   所有子進程被swapped的頁數的和,當前沒用
    exit_signal=17           該進程結束時,向父進程所發送的信號
    task_cpu(task)=0         運行在哪個CPU上
    task_rt_priority=0       實時進程的相對優先級別
    task_policy=0            進程的調度策略,0=非實時進程,1=FIFO實時進程;2=RR實時進程

進程的總Cpu時間processCpuTime = utime + stime + cutime + cstime
線程的總Cpu時間threadCpuTime = utime + stime + cutime + cstime

兩次採集時間片的數據獲取進程CPU佔用率
CPU佔用率 = (進程T2-進程T1)/(系統T2-系統T1) 的時間片比值

注:7.0以上的Android系統,/proc/stat無權限獲取。



四、流量

流量 :表示當前進程網絡的使用情況。

有兩種方法:

  • 通過Android提供的TrafficStats類來獲取;
  • 通過獲取proc文件內容來計算。

先看一下GT3.1採用的第一種方法:

TrafficStats源碼查看TrafficStats類是由Android提供的一個從你的手機開機開始,累計到現在使用的流量總量,或者統計某個或多個進程或應用所使用的流量,當然這個流量包括的Wifi和移動數據網Gprs。

	//系統流量統計:
    TrafficStats.getTotalRxBytes() ——獲取從此次開機起總接受流量(流量是分爲上傳與下載兩類的);
    TrafficStats.getTotalTxBytes()——獲取從此次開機起總髮送流量;
    TrafficStats.getMobileRxBytes()——獲取從此次開機起不包括Wifi的接受流量,即只統計數據網Gprs接受的流量;
    TrafficStats.getMobileTxBytes()——獲取從此次開機起不包括Wifi的發送流量,即只統計數據網Gprs發送的流量;
    //進程流量統計:
    TrafficStats.getUidRxBytes(mUid)
    TrafficStats.getUidTxBytes(mUid)  

獲取進程流量的方法:

u0_a開頭的都是Android的應用進程,Android的應用的UID是從10000開始,到19999結束。

	//獲取流量數據,上行和下行
	//這裏mUid是應用的uid,非進程id pid,注意區分
	//uid獲取可根據包名得到,方法如下:
	public static int getUidByPkgName(String pkgname)  {
        PackageManager pm = getPackageManager();
        try {
            ApplicationInfo ai = pm.getApplicationInfo(pkgname, 0);
            Log.i(TAG,String.valueOf(ai.uid));
            return ai.uid;
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
            return 0;
        }
	}
	public  static TrafficInfo collect(int mUid) {
        long upload  = TrafficStats.getUidRxBytes(mUid);
        long download = TrafficStats.getUidTxBytes(mUid);
	}

GT3.1開源獲取流量數據代碼:

https://github.com/Tencent/GT/blob/ed3a289a897d0ea14676a7c7d92344f5b398991e/android/GT_APP/app/src/main/java/com/tencent/wstt/gt/api/utils/NetUtils.java

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章