如何获取进程内存使用情况

    关于进程的内存占用情况查询,大家可以参考国外论坛的一个帖子(http://stackoverflow.com/questions/2298208/how-to-discover-memory-usage-of-my-application-in-android),这个帖子在国内被转载颇多,很有参考价值,因为其中对"Pss", "PrivateDirty"和 "SharedDirty"的概念做了一定阐述,使大家看到这几个参数时不会云里雾里。

    后面跟帖中也有打印进程内存使用情况的代码,还附有跟帖人对那段代码的疑问,代码如下。代码中打印信息的循环看似多余,明显,由于输入数组pids[]只有一个元素,返回的memoryInfoArray[]数组也只会含有一个元素,那段循环的意义就只有增强代码的可扩展性了。

ActivityManager activityManager = (ActivityManager) context.getSystemService(ACTIVITY_SERVICE);
MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
activityManager.getMemoryInfo(memoryInfo);

Log.i(TAG, " memoryInfo.availMem " + memoryInfo.availMem + "\n" );
Log.i(TAG, " memoryInfo.lowMemory " + memoryInfo.lowMemory + "\n" );
Log.i(TAG, " memoryInfo.threshold " + memoryInfo.threshold + "\n" );

List<RunningAppProcessInfo> runningAppProcesses = activityManager.getRunningAppProcesses();

Map<Integer, String> pidMap = new TreeMap<Integer, String>();
for (RunningAppProcessInfo runningAppProcessInfo : runningAppProcesses)
{
    pidMap.put(runningAppProcessInfo.pid, runningAppProcessInfo.processName);
}
Collection<Integer> keys = pidMap.keySet();

for(int key : keys)
{
    int pids[] = new int[1];
    pids[0] = key;
    android.os.Debug.MemoryInfo[] memoryInfoArray = activityManager.getProcessMemoryInfo(pids);
    for(android.os.Debug.MemoryInfo pidMemoryInfo: memoryInfoArray)
    {
        Log.i(TAG, String.format("** MEMINFO in pid %d [%s] **\n",pids[0],pidMap.get(pids[0])));
        Log.i(TAG, " pidMemoryInfo.getTotalPrivateDirty(): " + pidMemoryInfo.getTotalPrivateDirty() + "\n");
        Log.i(TAG, " pidMemoryInfo.getTotalPss(): " + pidMemoryInfo.getTotalPss() + "\n");
        Log.i(TAG, " pidMemoryInfo.getTotalSharedDirty(): " + pidMemoryInfo.getTotalSharedDirty() + "\n");
    }
}
   在看到上述代码之前,自己按照API说明也写了类似代码如下,包含了更多的输出参数。如果要检查其他进程的内存使用情况,可略去循环中的条件判断。按stackoverflow.com中帖子的说法 Pss的值是最能表明进程使用内存状况

public long getmem_SELF() {
        ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);

        List<RunningAppProcessInfo> procInfo = am.getRunningAppProcesses();
        for (RunningAppProcessInfo runningAppProcessInfo : procInfo) {  
        	System.out.println(runningAppProcessInfo.processName+ String.format(",pid = %d", runningAppProcessInfo.pid));  
        	if( runningAppProcessInfo.processName.indexOf(this.getPackageName()) != -1 )
        	{
        		int pids[] = {runningAppProcessInfo.pid};
        		Debug.MemoryInfo self_mi[] = am.getProcessMemoryInfo(pids);
        		StringBuffer  strbuf = new StringBuffer();
        		strbuf.append(" proccess Name:").append(runningAppProcessInfo.processName)
        			.append("\n pid:").append(runningAppProcessInfo.pid)
        			.append("\n dalvikPrivateDirty:").append(self_mi[0].dalvikPrivateDirty)
	    			.append("\n dalvikPss:").append(self_mi[0].dalvikPss)
	    			.append("\n dalvikSharedDirty:").append(self_mi[0].dalvikSharedDirty)
	    			.append("\n nativePrivateDirty:").append(self_mi[0].nativePrivateDirty)
	    			.append("\n nativePss:").append(self_mi[0].nativePss)
	    			.append("\n nativeSharedDirty:").append(self_mi[0].nativeSharedDirty)
	    			.append("\n otherPrivateDirty:").append(self_mi[0].otherPrivateDirty)
	    			.append("\n otherPss:").append(self_mi[0].otherPss)
	    			.append("\n otherSharedDirty:").append(self_mi[0].otherSharedDirty)
	    			.append("\n TotalPrivateDirty:").append(self_mi[0].getTotalPrivateDirty())
	    			.append("\n TotalPss:").append(self_mi[0].getTotalPss())
	    			.append("\n TotalSharedDirty:").append(self_mi[0].getTotalSharedDirty());
        		Log.v("TEST",strbuf.toString());
        	}
	}
	return 0;
}

翻译:"Pss", "PrivateDirty"和 "SharedDirty"有什么区别

   Android(亦即Linux)中,大量内存实际由多个进程共享,所以一个进程实际占用多少内存并不明确。甚至不太清楚哪些分页被添加到磁盘。

    这样,要是你要获取所有实际映射在每个进程的物理内存值,然后试图加总求和,你可能会得到一个远大于实际内存总量的值。

    Pss是考虑共享内存的内核计算尺度 -- 基本上一个进程的每个内存页面被按一个比率缩减,这个比率和同样使用该页面的其他进程的数量有关。理论上你可以累计所有进程的Pss占用量来检查所有进程的内存占用量,也可以比较进程的Pss来大致发现进程各自的权重。

    另一个有趣的参数是PrivateDirty,它基本上是进程内不能被分页到磁盘的内存,也不和其他进程共享。查看进程的内存用量的另一个途径,就是当进程结束时刻,系统可用内存的变化情况(也可能会很快并入高速缓冲或其他使用该内存区的进程,[微笑这样一来,企图就落空了:-)])。

原文

But as to what the difference is between "Pss", "PrivateDirty", and "SharedDirty"... well now the fun begins.

A lot of memory in Android (and Linux systems in general) is actually shared across multiple processes. So how much memory a processes uses is really not clear. Add on top of that paging out to disk (let alone swap which we don't use on Android) and it is even less clear.

Thus if you were to take all of the physical RAM actually mapped in to each process, and add up all of the processes, you would probably end up with a number much greater than the actual total RAM.

The Pss number is a metric the kernel computes that takes into account memory sharing -- basically each page of RAM in a process is scaled by a ratio of the number of other processes also using that page. This way you can (in theory) add up the pss across all processes to see the total RAM they are using, and compare pss between processes to get a rough idea of their relative weight.

The other interesting metric here is PrivateDirty, which is basically the amount of RAM inside the process that can not be paged to disk (it is not backed by the same data on disk), and is not shared with any other processes. Another way to look at this is the RAM that will become available to the system when that process goes away (and probably quickly subsumed into caches and other uses of it).


你可能感兴趣的:(如何获取进程内存使用情况)