内存分析常用命令和总结

1. TOP

top 命令是 Linux 下常用的性能分析工具,能够 实时显示系统中各个进程的资源占用状况,类似于 Windows 的任务管理器。该命令可以按 CPU使用、内存使用和执行时间 对任务进行排序。

使用TOP查看到的具体信息:
在这里插入图片描述

接下来我们看一下每一行的具体意思:
第一行:Tasks — 任务(进程)
具体信息说明如下所示:
系统现在共有 515 个进程,其中处于 运行中 的有 1 个,514 个在 休眠(sleep),stoped 状态的有0个,zombie 状态(僵尸)的有 0 个。
第二行:内存状态
从左到右分别代表:total,物理内存总量;used,使用中的内存总量;free,空闲内存总量;buffers,缓存的内存量。
第三行:swap交换分区信息
从左到右分别代表:total,交换分区总量;used,使用的交换分区总量;free:空闲交换分区总量;cached,缓冲的交换分区总量。
第四行:cpu状态信息
800%代表是八核cpu;5%CPU被用户使用着,2%nice优先级为负的进程,67%sys内核空间占用CPU百分比;685%idle除了IO等待时间外的其他等待时间;iow:IO等待时间;irq、sirq硬中断和软中断。
对于内存监控,在 top 里我们要时刻监控 第三行 swap 交换分区的 used,如果这个数值在不断的变化,说明内核在不断进行内存和 swap 的数据交换,这是真正的内存不够用了。

第五行及以下,就是各进程(任务)的状态监控:
• 1)、PID:进程 id
• 2)、USER:进程所有者
• 3)、PR:进程优先级
• 4)、NI:nice 值。负值表示高优先级,正值表示低优先级
• 5)、VIRT:进程使用的虚拟内存总量。VIRT = SWAP + RES
• 6)、RES:进程使用的、未被换出的物理内存大小。RES = CODE + DATA
• 7)、SHR:共享内存大小
• 8)、S:进程状态。D = 不可中断的睡眠状态、R = 运行、 S = 睡眠、T = 跟踪 / 停止、Z = 僵尸进程
• 9)、%CPU — 上次更新到现在的 CPU 时间占用百分比
• 10)、%MEM:进程使用的物理内存百分比
• 11)、TIME+:进程使用的 CPU 时间总计,单位 1/100秒
• 12)、ARGS:进程名称(命令名 / 命令行)

四大内存指标
内存指标全称含义等价
USSUnique Set Size物理内存进程独占的内存
PSSProportional Set Size物理内存PSS = USS + 按比例包含共享库
RSSResident Set Size物理内存RSS= USS+ 包含共享库
VSSVirtual Set Size虚拟内存VSS= RSS+ 未分配实际物理内存

RSS 与 PSS 相似,都包含进程共享内存,但比较麻烦的是 RSS 并没有把共享内存大小全都平分到使用共享的进程头上,以至于所有进程的 RSS 相加会超过物理内存很多。而 VSS 是虚拟地址,它的上限与进程的可访问地址空间有关,和当前进程的内存使用关系并不大。比如有很多的 map 内存也被算在其中,我们都知道,file 的 map 内存对应的可能是一个文件或硬盘,或者某个奇怪的设备,它与进程使用内存并没有多少关系。

dumpsys meminfo 命令解析

dumpsys meminfo可获取到的具体信息如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

划分类型排序指标含义
processPSS以进程的PSS从大到小依次排序显示,每行显示一个进程,一般用来做初步的竞品分析
OOM adjPSS展示当前系统内部运行的所有Android进程的内存状态和被杀顺序,越靠近下方的进程越容易被杀,排序按照一套复杂的算法,算法涵盖了前后台、服务或节目、可见与否、老化等
categoryPSS以Dalvik/Native/.art mmap/.dex map等划分并按降序列出各类进程的总PSS分布情况
total总内存、剩余内存、可用内存、其他内存

查看单个 App 进程的内存信息:adb shell dumpsys meminfo --package

在这里插入图片描述
• 1)、Native Heap:表示 native 的内存占用,如果持续上升,则可能有泄漏。
• 2)、Java Heap:表示 Java 层的内存占用。

查看 Views、Activities、AppContexts 数量变化情况
如果 Views 与 Activities、AppContexts 持续上升,则表明有内存泄漏的风险。

内存问题总结:

  1. 内部类是一种危险的编码方式
    每个类实例都具有一个this0这样的成员,当它的内部类需要访问外部类的成员时,内部类就会持有外部类的 this0,通过this0就可以访问外部类所有的成员。同时也会持有外部类的引用;
    解决方案是在 Activity 关闭,即触发 onDestory 时解除内类和外部的引用关系。或者将内部类拉出来单独建一个类。

  2. 普通 Hanlder 内部类的问题
    这也是一个 this$0 间接引用的问题,对于 Handler 的解决方案一般可以归结为如下三个步骤:

    1. 把内类声明成 static:用来断绝 this$0 的引用。因为 static 描述的内类从 Java 编译原理的角度看,”内类“与”外类“相互独立,互相都没有访问对方成员变量的能力。
    2. 使用 WeakReference 来引用外部类的实例。
    3. 在外部类(如 Activity)销毁的时候使用 removeCallbackAndMessages 来移除回调和消息。
      这里需要在使用过程中注意对 WeakReference 进行判空。
  3. 使用系统服务时产生的内存问题
    我们通常都会使用 getSystemService 方法来获取系统服务,但是当在 Activity 中调用时,会默认把 Activity 的 Context 传给系统服务,在某些不确定的情况下,某些系统服务内部会产生异常,从而 hold 住外界传入的 Context。
    解决方案是 直接使用 Applicaiton 的 Context 去获取系统服务。

  4. 把 WebView 类型的泄漏装进垃圾桶进程
    对应 WebView 来说,其 网络延时、引擎 Session 管理、Cookies 管理、引擎内核线程、HTML5 调用系统声音、视频播放组件等产生的引用链条无法及时打断,造成的内存问题基本上可以用”无解“来形容。
    解决方案是我们可以 把 WebView 装入另一个进程。 具体为在 AndroidManifes 中对当前的 Activity 设置 android:process 属性即可,最后,在 Activity 的 onDestory 中退出进程,这样即可基本上终结 WebView 造成的泄漏。

  5. Handler / FrameLayout 的 postDelyed 方法触发的内存问题
    我们需要在 onDestory 中使用 removeCallbackAndMessage 移除回调和消息,在使用到 Handler / FrameLayout 的 postDelyed 方法时,我们需要调用 removeCallbacks 去移除实现控件内部的延时器对 Runnable 内类的持有。

  6. 图片放错资源目录
    在做资源适配的时候,因为需要考虑到 APK 的瘦身问题,无法为每张图片在每个 drawable / mipmap 目录下安置一张适配图片的副本。很多人不知道图片应该放哪个目录,如果放到分辨率低的目录如 hdpi 目录,则可能会造成内存问题,这个时候建议尽量问设计人员要高品质图片然后往高密度目录下方,如 xxhdpi 目录,这样 在低密屏上”放大倍数“是小于1的,在保证画质的前提下,内存也是可控的。也可以使用 Drawable.createFromSream 替换 getResources().getDrawable 来加载,这样便可以绕过 Android 的默认适配规则。

  7. 使用 ViewStub 进行占位
    应该使用 ViewStub 对那些没有马上用到的资源去做延迟加载,并且还有很多大概率不会出现的 View 更要去做懒加载,这样可以等到要使用时再去为它们分配相应的内存。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值