由于app要接入某一厂商,对内存有严格的使用要求,比如初始内存要小于多少M,使用过程最大内存不得超过多少M等条件。对于这些量化的数据,我们需要重哪里获取呢。 在开发阶段,我们除了用Android提供的工具,比如 Android Profiler 、MAT 等工具来通过可视化的方式洞察到我们应用程序的占用内存,Android中也提供了详细命令让我们使用。
Android 运行时 (ART) 和 Dalvik 虚拟机使用分页和内存映射来管理内存。这意味着应用修改的任何内存,无论修改的方式是分配新对象还是轻触内存映射的页面,都会一直驻留在 RAM 中,并且无法换出。要从应用中释放内存,只能释放应用保留的对象引用,使内存可供垃圾回收器回收。
故内存的大小关系:VSS >= RSS >= PSS >= USS
Dalvik 堆局限于每个应用进程的单个虚拟内存范围。这定义了逻辑堆大小,该大小可以根据需要增长,但不能超过系统为每个应用定义的上限。
堆的逻辑大小与堆使用的物理内存量不同。在检查应用堆时,Android 会计算按比例分摊的内存大小 (PSS) 值,该值同时考虑与其他进程共享的脏页和干净页,但其数量与共享该 RAM 的应用数量成正比。此 (PSS) 总量是系统认为的物理内存占用量 Dalvik 堆不压缩堆的逻辑大小,这意味着 Android 不会对堆进行碎片整理来缩减空间。只有当堆末尾存在未使用的空间时,Android 才能缩减逻辑堆大小。但是,系统仍然可以减少堆使用的物理内存。垃圾回收之后,Dalvik 遍历堆并查找未使用的页面,然后使用 madvise 将这些页面返回给内核。因此,大数据块的配对分配和解除分配应该使所有(或几乎所有)使用的物理内存被回收。但是,从较小分配量中回收内存的效率要低得多,因为用于较小分配量的页面可能仍在与其他尚未释放的数据块共享。
为了维持多任务环境的正常运行,Android 会为每个应用的堆大小设置硬性上限。不同设备的确切堆大小上限取决于设备的总体可用 RAM 大小。如果您的应用在达到堆容量上限后尝试分配更多内存,则可能会收到 OutOfMemoryError。
常用的内存调优分析命令:
dumpsys meminfodumpsys procstatscat /proc/meminfofreevmstat命令均在 adb shell 使用
可以查看各个进程使用状况 通过这个命令我们可以一下了解到我们的手机目前占用内存从大到小的排序,com.hugh.basis这款是我打开的调试app,在app开启后,我们也可通过此命令来看我们应用的初始内存占用多少
PSS是实际使用的物理内存,这是对应用 RAM 占用情况的衡量,考虑了在进程之间共享 RAM 页的情况,PSS 结果一个比较好的特性是,您可以将所有进程的 PSS 相加来确定所有进程正在使用的实际内存。这意味着 PSS 适合测定进程的实际 RAM 比重和比较其他进程的 RAM 使用情况与可用总 RAM。
RAM: 随机存取存储器,也称做手机内存。内存越大,我们可以读写的动态数据就越多,这样手机的反应速度就会越快。
dumpsys meminfo 命令的输出结果分以下4部分:
序列类型排序解释1processPSS以进程的PSS从大到小依次排序显示,每行显示一个进程;2OOM adjPSSPSS Native/System/Persistent/Foreground/Visible/Perceptible/A Services/Home/B Services/Cached,分别显示每类的进程情况3categoryPSS以Dalvik/Native/.art mmap/.dex map等划分的各类进程的总PSS情况4total-总内存、剩余内存、可用内存、其他内存我们具体看下输出命令
dumpsys meminfo Applications Memory Usage (in Kilobytes): Uptime: 2964163 Realtime: 2964163 Total PSS by process: //对应第一部分 以进程的PSS从大到小依次排序显示,每行显示一个进程 193,237K: system (pid 1529) 130,817K: com.miui.home (pid 3080 / activities) 129,076K: com.tencent.mm (pid 4578) 87,370K: com.android.systemui (pid 1948 / activities) 69,517K: surfaceflinger (pid 572) 64,283K: com.hugh.basis (pid 10651 / activities) ... Total PSS by OOM adjustment://第二部分 以特定的类显示格子内部进程占用大小,比如前台进程,服务进程等 347,695K: Native 70,373K: surfaceflinger (pid 575) 58,815K: logd (pid 447) 17,732K: libweexjsb.so (pid 13870) ... 494,426K: Persistent 244,529K: system (pid 1565) 114,672K: com.android.systemui (pid 1978 / activities) 24,642K: com.android.phone (pid 2158) ... 92,509K: Foreground 60,764K: com.hugh.basis (pid 15218 / activities) 27,542K: com.miui.securitycenter.remote (pid 2830) 4,203K: com.mobiletools.systemhelper:register (pid 5769) Total PSS by category://第三部分,以Dalvik/Native/.art mmap/.dex map等划分的各类进程的总PSS情况 399,675K: Dalvik 295,839K: Native 124,249K: .oat mmap 82,444K: .dex mmap 77,968K: Dalvik Other ... //第四部分,整体RAM的使用情况 Total RAM: 2,758,952K (status moderate) Free RAM: 1,067,004K ( 407,072K cached pss + 616,164K cached kernel + 43,768K free) Used RAM: 2,329,444K (1,937,064K used pss + 392,380K kernel) Lost RAM: -388,634K ZRAM: 125,548K physical used for 559,004K in swap (1,048,572K total swap) Tuning: 256 (large 512), oom 322,560K, restore limit 107,520K (high-end-gfx)可以查看各个进程使用状况 如果你想看一个进程更详细内存占用,就可以加上包名或进程名,-d 标记会输出更多与 Dalvik 和 ART 内存占用情况相关的信息。
一般情况下,仅需关注 Pss Total 和 Private Dirty 列
如果我们想要获取某一时段我们应用的占用内存,包括应用在后台运行的时长以及在该期间内的内存占用情况。它可以帮助您快速找到应用中的低效环节和不当行为(如内存泄漏),这些问题可能会影响应用的表现,特别是在低内存设备上运行时。
比如要获取过去三小时内应用的内存占用情况统计信息
adb shell dumpsys procstats --hours 3我们可以自定义开始的阶段以及结束的阶段来获取某一个业务场景消耗内存的平均值以及最大值
dumpsys procstats --start-testingdumpsys procstats 应用包名dumpsys procstats --stop-testing我们来看看 dumpsys procstats 应用包名 的输出日志,从下面的示例中可以看出,输出会显示应用运行时间的百分比,以及 PSS、USS 和 RSS(minPSS-avgPSS-maxPSS/minUSS-avgUSS-maxUSS/minRSS-avgRSS-maxRSS over 样本数)。
dumpsys procstats com.hugh.basis CURRENT STATS: System memory usage: SOff/Norm: 1 samples: Cached: 600MB min, 600MB avg, 600MB max Free: 39MB min, 39MB avg, 39MB max ZRam: 178MB min, 178MB avg, 178MB max Kernel: 389MB min, 389MB avg, 389MB max Native: 341MB min, 341MB avg, 341MB max ... Per-Package Stats: * com.hugh.basis / u0a975 / v1: * com.hugh.basis / u0a975 / v1: TOTAL: 21% (57MB-58MB-60MB/53MB-54MB-56MB over 17) Top: 21% (57MB-58MB-60MB/53MB-54MB-56MB over 17) Summary: * com.hugh.basis / u0a975 / v1: TOTAL: 21% (57MB-58MB-60MB/53MB-54MB-56MB over 17) Top: 21% (57MB-58MB-60MB/53MB-54MB-56MB over 17)对于cache和buffer也是系统可以使用的内存。所以系统总的可用内存为 MemFree+Buffers+Cached
查看可用内存,缺省单位KB。该命令比较简单、轻量,专注于查看剩余内存情况。数据来源于/proc/meminfo。
capricorn:/ $ free total used free shared buffers Mem: 2825166848 2775478272 49688576 6356992 43368448 -/+ buffers/cache: 2732109824 93057024 Swap: 1073737728 565772288 507965440不仅可以查看内存情况,还可以查看进程运行队列、系统切换、CPU时间占比等情况,另外该指令还是周期性地动态输出。
procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu---- r b swpd free buff cache si so bi bo in cs us sy id wa 3 0 552320 47316 42908 535840 12 27 1071 105 2 1386 15 18 67 0