[性能]安卓获取内存

前言

Android 线上、线下获取内存值的方式。
Android Q 对于线上客户端数据采集有影响,在文中有说明。

线下 adb shell

1. cat /proc [ /meminfo | /<pid>/meminfo ]

案例:cat proc/meminfo 获取手机整体内存信息

dipper:/ $ cat /proc/meminfo
MemTotal:        5764820 kB
MemFree:          134792 kB
MemAvailable:    2791948 kB
Buffers:          198508 kB
Cached:          2039260 kB
SwapCached:        30748 kB
Active:          2687728 kB
Inactive:        1038232 kB
Active(anon):    1203052 kB
Inactive(anon):   460412 kB
Active(file):    1484676 kB
Inactive(file):   577820 kB
Unevictable:      161012 kB
Mlocked:          161012 kB
SwapTotal:       2621436 kB
SwapFree:        2022464 kB
Dirty:               548 kB
Writeback:             0 kB
AnonPages:       1643692 kB
Mapped:           866444 kB
Shmem:             14664 kB
Slab:             454188 kB
SReclaimable:     198228 kB
SUnreclaim:       255960 kB
KernelStack:       77744 kB
PageTables:       105048 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:     5503844 kB
Committed_AS:   99980240 kB
VmallocTotal:   263061440 kB
VmallocUsed:           0 kB
VmallocChunk:          0 kB
CmaTotal:         204800 kB
CmaFree:             156 kB
2. dumpsys meminfo <pid | processName>

** 通过 dumpsys meminfo -h 可以获取帮助**

dipper:/ $ dumpsys meminfo -h
meminfo dump options: [-a] [-d] [-c] [-s] [--oom] [process]
  -a: include all available information for each process.
  -d: include dalvik details.
  -c: dump in a compact machine-parseable representation.
  -s: dump only summary of application memory usage.
  -S: dump also SwapPss.
  --oom: only show processes organized by oom adj.
  --local: only collect details locally, don't call process.
  --package: interpret process arg as package, dumping all
             processes that have loaded that package.
  --checkin: dump data for a checkin
  --proto: dump data to proto
If [process] is specified it can be the name or 
pid of a specific process to dump.

案例: 获取指定 app 的内存信息

dipper:/ $ dumpsys meminfo -a com.xiaomi.xmsf
Applications Memory Usage (in Kilobytes):
Uptime: 3335578435 Realtime: 4039602043

** MEMINFO in pid 7549 [com.xiaomi.xmsf] **
                   Pss      Pss   Shared  Private   Shared  Private  SwapPss     Heap     Heap     Heap
                 Total    Clean    Dirty    Dirty    Clean    Clean    Dirty     Size    Alloc     Free
                ------   ------   ------   ------   ------   ------   ------   ------   ------   ------
  Native Heap     4136        0      532     4124        0        0     1375    17484    15882     1601
  Dalvik Heap     2604        0      284     2596        0        0       63     3740     1870     1870
 Dalvik Other      733        0      100      732        0        0       26                           
        Stack       24        0        4       24        0        0       12                           
       Ashmem        0        0       12        0        0        0        0                           
    Other dev       65        0      268        0        0       64        0                           
     .so mmap      405        0      768       44    11348        0       21                           
    .jar mmap      261        0        0        0    10256        0        0                           
    .apk mmap        0        0        0        0       20        0        0                           
    .dex mmap     2448     2444        0        4        4     2444        4                           
    .oat mmap     1205        0        0        0    39116        0        0                           
    .art mmap     1615        4    11488     1348      116        4      202                           
   Other mmap       20        0       32       12      160        0        0                           
      Unknown      756        0      348      748        0        0      326                           
        TOTAL    16301     2448    13836     9632    61020     2512     2029    21224    17752     3471
 
 Dalvik Details
        .Heap     2112        0        0     2112        0        0        0                           
         .LOS       16        0        0       16        0        0       15                           
      .Zygote      460        0      284      452        0        0       48                           
   .NonMoving       16        0        0       16        0        0        0                           
 .LinearAlloc      313        0       56      312        0        0       22                           
          .GC      304        0       32      304        0        0        4                           
 .IndirectRef      116        0       12      116        0        0        0                           
   .Boot vdex        0        0        0        0        4        0        0                           
     .App dex     1596     1592        0        4        0     1592        4                           
    .App vdex      852      852        0        0        0      852        0                           
     .App art      548        4        0      544        0        4       52                           
    .Boot art     1067        0    11488      804      116        0      150                           
 
 App Summary
                       Pss(KB)
                        ------
           Java Heap:     3948
         Native Heap:     4124
                Code:     2492
               Stack:       24
            Graphics:        0
       Private Other:     1556
              System:     4157
 
               TOTAL:    16301       TOTAL SWAP PSS:     2029
 
 Objects
               Views:        2         ViewRootImpl:        0
         AppContexts:        5           Activities:        0
              Assets:       17        AssetManagers:        0
       Local Binders:       28        Proxy Binders:       35
       Parcel memory:       57         Parcel count:       65
    Death Recipients:        1      OpenSSL Sockets:        5
            WebViews:        0
 
 SQL
         MEMORY_USED:      330
  PAGECACHE_OVERFLOW:       42          MALLOC_SIZE:      117
 
 DATABASES
      pgsz     dbsz   Lookaside(b)          cache  Dbname
         4       20             57         2/18/3  /data/user/0/com.xiaomi.xmsf/databases/crash.db
         4    16248             21      253/153/2  /data/user/0/com.xiaomi.xmsf/databases/traffic.db

线上安卓客户端

1. ActivityManager.getProcessMemoryInfo(pids: IntArray)

在 Android Q 之后只能获取同 uid 进程的内存数据,而且频率受系统底层限制,默认是 300000 ms (5 min)。

可以通过 adb shell settings put global activity_manager_constants ‘memory_info_throttle_time=1000’ 修改底层的频率限制。(需要开启 USB 调试的安全调试模式)

	/**
     * 通过 ActivityManager 获取进程的内存信息,
     * 但是在 Android Q 以上受系统底层限制,连续频繁采样会获取一样的数据,
     * 具体间隔可以通过 getMemoryInfoThrottleTime(context: Context) 获取。
     *
     * @see getMemoryInfoThrottleTime(context: Context)
     *
     * @return 返回精准的 pss 内存信息
     */
    fun getThrottledMemoryInfo(context: Context, pid: Int = myPid()): Debug.MemoryInfo {
        val memInfo: Debug.MemoryInfo?
        val manager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
        val memInfos: Array<Debug.MemoryInfo> = manager.getProcessMemoryInfo(IntArray(1) { pid })
        memInfo = memInfos[0]
        return memInfo
    }

    private const val SETTINGS_NAME = "activity_manager_constants"
    private const val MEMORY_INFO_THROTTLE_TIME_KEY_PATTERN = "memory_info_throttle_time="
    private const val THROTTLE_VALUE_NAME_PATTERN = "$MEMORY_INFO_THROTTLE_TIME_KEY_PATTERN\\d*"
    // 安卓官方默认的采集间隔是 300 s
    private const val DEFAULT_THROTTLE_TIME = 300000L
    
	// 获取系统的 memory_info_throttle_time 的数值
    @RequiresApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
    fun getMemoryInfoThrottleTime(context: Context): Long {
        val resolver = context.contentResolver
        val constants = Settings.Global.getString(resolver, SETTINGS_NAME)
        var value = DEFAULT_THROTTLE_TIME
        if (constants != null) {
            val regex = Regex(THROTTLE_VALUE_NAME_PATTERN)
            val find = regex.find(constants)
            if (find != null && find.groupValues.isNotEmpty()) {
                val throttle = find.groupValues[0]
                val valueStr = throttle.substring(MEMORY_INFO_THROTTLE_TIME_KEY_PATTERN.length, throttle.length)
                value = try {
                    valueStr.toLong()
                } catch (e: NumberFormatException) {
                    DEFAULT_THROTTLE_TIME
                }
            }
        }
        return value
    }
2. Debug.getMemoryInfo(memInfo: Debug.MemoryInfo)

只能获取当进程的内存信息。但在 Android Q 之后依旧可以频繁调用。
会缺失 graphicis 的数值,其实最后返回的 totalPss 数值是偏小的。

    /**
     * 在 Android Q 以上也可以及时获取最新内存信息的方法,
     * 但存在以下问题
     *  1. 功耗较高,耗时波动在 40ms - 120ms 之间。
     *  2. 缺失 graphics 的数值,在 GPU 占用高的场景与真实数值差距较大。
     *
     * @return 返回 pss 内存信息,
     */
    fun getDebugMemoryInfo(): Debug.MemoryInfo {
        val memInfo = Debug.MemoryInfo()
        Debug.getMemoryInfo(memInfo)
        return memInfo
    }
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值