怎样发现android中应用的内存使用情况

Note that memory usage on modern operating systems like Linux is an extremely complicated and difficult to understand area. In fact the chances of you actually correctly interpreting whatever numbers you get is extremely low. (Pretty much every time I look at memory usage numbers with other engineers, there is always a long discussion about what they actually mean that only results in a vague conclusion.)

注意到操作系统中内存的使用情况(比如linux)是一个相当复杂和很难理解的领域。实际上,真正正确的解释出到底使用了多少内存的可能性是很小的(尤其是当我每次跟其它工程师一起看内存使用情况时,我们经常会长时间的讨论到底他们是什么意思,最终得到一个似是而非的模糊推论)。

First thing is to probably read the last part of this article which has some discussion of how memory is managed on Android:

http://android-developers.blogspot.com/2010/02/service-api-changes-starting-with.html

首先,最好去看下这篇文章的最后一部分,这部分讨论了android里面怎么管理内存

Now ActivityManager.getMemoryInfo() is our highest-level API for looking at overall memory usage. This is mostly there to help an application gauge how close the system is coming to having no more memory for background processes, thus needing to start killing needed processes like services. For pure Java applications, this should be of little use, since the Java heap limit is there in part to avoid one app from being able to stress the system to this point.

ActivityManager.getMemoryInfo() 是我们找到所有内存使用情况的最高层的接口。在系统没有更多内存为后台进程时,它可以最大程度帮助应用来确定怎样关闭,因此需要杀掉一些进程比如服务。对于纯粹的java应用来说,这基本没啥用途,既然java堆的限制能大多数情况下避免一个应用来压迫系统到需要杀死进程的程度。

Going lower-level, you can use the Debug API to get raw kernel-level information about memory usage:http://developer.android.com/intl/de/reference/android/os/Debug.html#getMemoryInfo(android.os.Debug.MemoryInfo)

在底层次上,又可以使用调试api来得到内核层次的内存信息。

Note starting with 2.0 there is also an API, ActivityManager.getProcessMemoryInfo, to get this information about another process:http://developer.android.com/intl/de/reference/android/app/ActivityManager.html#getProcessMemoryInfo(int[])

2.0版本以后,又增加了一个API, ActivityManager.getProcessMemoryInfo来获得其他进程的内存使用情况。它将返回一个低层次的内存信息结构,如下所示:

This returns a low-level MemoryInfo structure with all of this data:

    /** The proportional set size for dalvik. */
    public int dalvikPss;
    /** The private dirty pages used by dalvik. */
    public int dalvikPrivateDirty;
    /** The shared dirty pages used by dalvik. */
    public int dalvikSharedDirty;

    /** The proportional set size for the native heap. */
    public int nativePss;
    /** The private dirty pages used by the native heap. */
    public int nativePrivateDirty;
    /** The shared dirty pages used by the native heap. */
    public int nativeSharedDirty;

    /** The proportional set size for everything else. */
    public int otherPss;
    /** The private dirty pages used by everything else. */
    public int otherPrivateDirty;
    /** The shared dirty pages used by everything else. */
    public int otherSharedDirty;

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

但是, "Pss", "PrivateDirty", and "SharedDirty"... 的不同是啥呢?有趣的事情开始了。。。

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.

android下(Linux系统下一般下也是这样的)许多内存是供多个进程共享的。因此,一个进程到底使用了多少内存是非常不清晰的。而且,由于高端页面映射到磁盘里(更不用说交换了,但android中不使用swap),导致内存使用情况更难搞清。

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.

因此,如果你想搞清到底每一个进程到底有多少空间映射到了RAM上,或者所有进程有多少空间映射到RAM上,你往往会得到一个比实际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.

Pss的值是kernel计算包含共享内存时得到的一个数值--基本上RAM中的每一个page都通过使用该page的进程数目的比例计算出来。这种方法在理论上通过所有进程来看使用的全部RAM,并且比较PSS在进程间的使用情况来获得的一个粗糙的权重计算出了Pss。

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).

另一个计量方式是PrivateDirty,它只统计进程内部使用的没有被映射到磁盘(它不是由同一个磁盘的数据支持)的RAM数目,并且该RAM没有被任何其它进程共享。另一个来获得该值的方式是当这个进程消失时,系统收回的RAM数目(该内存很可能很快被并入高速缓存或者被其它用途使用)

That is pretty much the SDK APIs for this. However there is more you can do as a developer with your device.

这是SDK APIs相当喜欢的方式。但是作为一个开发人员,你可以做到更多。

Using adb, there is a lot of information you can get about the memory use of a running system. A common one is the command "adb shell dumpsys meminfo" which will spit out a bunch of information about the memory use of each Java process, containing the above info as well as a variety of other things. You can also tack on the name or pid of a single process to see, for example "adb shell dumpsys meminfo system" give me the system process:

使用adb,你可以得到正在运行系统的很多内存使用信息。最常用的是使用 "adb shell dumpsys meminfo" 命令,它将会列出一系列关于java进程使用内存的信息,包含以上列出的信息,还包含一些其它的信息。你也可以跟踪进程的名字或者pid来查看其内存使用情况,比如"adb shell dumpsys meminfo system"将会得到system进程使用内存的信息。

** MEMINFO in pid 890 [system] **
                    native   dalvik    other    total
            size:    10940     7047      N/A    17987
       allocated:     8943     5516      N/A    14459
            free:      336     1531      N/A     1867
           (Pss):     4585     9282    11916    25783
  (shared dirty):     2184     3596      916     6696
    (priv dirty):     4504     5956     7456    17916

 Objects
           Views:      149        ViewRoots:        4
     AppContexts:       13       Activities:        0
          Assets:        4    AssetManagers:        4
   Local Binders:      141    Proxy Binders:      158
Death Recipients:       49
 OpenSSL Sockets:        0

 SQL
            heap:      205          dbFiles:        0
       numPagers:        0   inactivePageKB:        0
    activePageKB:        0

The top section is the main one, where "size" is the total size in address space of a particular heap, "allocated" is the kb of actual allocations that heap thinks it has, "free" is the remaining kb free the heap has for additional allocations, and "pss" and "priv dirty" are the same as discussed before specific to pages associated with each of the heaps.

最上边的片段是主要内容,“size”是一个具体堆的地址空间的总和。 "allocated"是以Kb为单位的堆已经实际分配空间, "free" 是堆上剩余的以Kb为单位的可以分配的空间。"pss" 和 "priv dirty" 跟上述已经解释的相同

If you just want to look at memory usage across all processes, you can use the command "adb shell procrank". Output of this on the same system looks like:

如果你仅仅想查看下所有进程的内存使用情况,可以简单使用 "adb shell procrank"命令,得到的结果如下

  PID      Vss      Rss      Pss      Uss  cmdline
  890   84456K   48668K   25850K   21284K  system_server
 1231   50748K   39088K   17587K   13792K  com.android.launcher2
  947   34488K   28528K   10834K    9308K  com.android.wallpaper
  987   26964K   26956K    8751K    7308K  com.google.process.gapps
  954   24300K   24296K    6249K    4824K  com.android.phone
  948   23020K   23016K    5864K    4748K  com.android.inputmethod.latin
  888   25728K   25724K    5774K    3668K  zygote
  977   24100K   24096K    5667K    4340K  android.process.acore
...
   59     336K     332K      99K      92K  /system/bin/installd
   60     396K     392K      93K      84K  /system/bin/keystore
   51     280K     276K      74K      68K  /system/bin/servicemanager
   54     256K     252K      69K      64K  /system/bin/debuggerd

Here the Vss and Rss columns are basically noise (these are the straight-forward address space and RAM usage of a process, where if you add up the RAM usage across processes you get an ridiculously large number).

这里,Vss和Rss更加令人闹心(他们是一个进程直接的地址空间和Ram使用情况,如果你将所有进程的Ram使用情况相加,你将会得到一个相当大的数值)

Pss is as we've seen before, and Uss is Priv Dirty.

Pss 前面我们已经解释过了。而Uss对应的是 Priv Dirty

Interesting thing to note here: Pss and Uss are slightly (or more than slightly) different than what we saw in meminfo. Why is that? Well procrank uses a different kernel mechanism to collect its data than meminfo does, and they give slightly different results. Why is that? Honestly I haven't a clue. I believe procrank may be the more accurate one... but really, this just leave the point: "take any memory info you get with a grain of salt; often a very large grain."

这里有个需要注意的地方:Pss和Uss有一点点不同(或许不是一小点)。为什么是这样呢?procrank 使用了一个不同于meminfo的内核机制来收集数据。为什么不同,其实我也有点迷惑。我认为procrank 或许会更精确。。。,但是实际上,这仅仅是由于这个观点“将所有的内存信息加在一起,你会得到一个更大的数值”

Finally there is the command "adb shell cat /proc/meminfo" that gives a summary of the overall memory usage of the system. There is a lot of data here, only the first few numbers worth discussing (and the remaining ones understood by few people, and my questions of those few people about them often resulting in conflicting explanations):

最后是这个指令“adb shell cat /proc/meminfo”,它给出了一个所有内存使用的情况。这里有许多数据,但是只有前面几个数值值得去分析下(其它剩余的几乎没人懂,并且懂的那一点点人也经常解释的相互冲突)

MemTotal:         395144 kB
MemFree:          184936 kB
Buffers:             880 kB
Cached:            84104 kB
SwapCached:            0 kB

MemTotal is the total amount of memory available to the kernel and user space (often less than the actual physical RAM of the device, since some of that RAM is needed for the radio, DMA buffers, etc).

MemTotal 是内核和用户控件的所有有效内存(这经常小于实际的RAM的大小,因为一些RAM空间被用于音频,DMA缓存等)

MemFree is the amount of RAM that is not being used at all. The number you see here is very high; typically on an Android system this would be only a few MB, since we try to use available memory to keep processes running

MemFree 是RAM的未被使用的空间总和。这里你看到的数值非常大;但是实际上,在android系统中,这将紧紧只有几个MB,因为我们会尽量有效使用内存来保持进程的运行。

Cached is the RAM being used for filesystem caches and other such things. Typical systems will need to have 20MB or so for this to avoid getting into bad paging states; the Android out of memory killer is tuned for a particular system to make sure that background processes are killed before the cached RAM is consumed too much by them to result in such paging.

Cached 是被用于文件系统或者其它事情的RAM空间。通常情况下,系统将需要20M左右的空间来避免进入坏页面映射状态;在 cached RAM被消耗的太多导致的这种情况之前,android的OOM将会被激发来杀死后台进程。

Have a look at pixelbeat.org/scripts/ps_mem.py which uses the techniques mentioned above to show used RAM for programs – pixelbeat Aug 13 '10 at 10:47

 I wrote a post on memory management and use of different tools to inspect your heap usage here macgyverdev.blogspot.com/2011/11/… if anyone finds it useful. –  JohanN  Nov 5 '11 at 10:13

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、下 4载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、下载 4使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、下载 4使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值