内存耗用分析:VSS/RSS/PSS/USS

  • VSS- Virtual Set Size 虚拟耗用内存(包含共享库占用的内存)
  • RSS- Resident Set Size 实际使用物理内存(包含共享库占用的内存)
  • PSS- Proportional Set Size 实际使用的物理内存(比例分配共享库占用的内存)
  • USS- Unique Set Size 进程独自占用的物理内存(不包含共享库占用的内存)

一般来说内存占用大小有如下规律:VSS >= RSS >= PSS >= USS

top  | grep app名称

ps  |  grep app名称

procrank | grep app名称

dumpsys meminfo app名称

前两个命令只能查到VSS RSS内存占用信息

而后面两个命令可以查出  PSS USS内存占用.

dumpsys meminfo 可以查出native和dalvik分别占用多少内存

dumpsys 用来给出手机中所有应用程序的信息,并且也会给出现在手机的状态。

dumpsys [Option]

               meminfo 显示内存信息

               cpuinfo 显示CPU信息

               account 显示accounts信息

               activity 显示所有的activities的信息

               window 显示键盘,窗口和它们的关系

               wifi 显示wifi信息

首先了解两个概念:

  • 私有内存(Dirty and Clean):
    进程独占内存。也就是进程销毁时可以回收的内存容量。通常private Dirty内存是最重要的部分,因为只被自己进程使用。Dirty内存是已经被修改的内存页,因此必须常驻内存(因为没有swap);Clean内存是已经映射持久文件使用的内存页(例如正在被执行的代码),因此一段时间不使用的话就可以置换出去。

  • 实际使用内存(PSS):
    将跨进程共享页也加入进来, 进行按比例计算PSS。这样能够比较准确的表示进程占用的实际物理内存。

通常我们需要关注PSS TOTALPrivate Dirty .

  • Dalvik Heap
    dalvik虚拟机分配的内存。PSS Total包含所有Zygote分配使用的内存,共享跨进程加权。PrivateDirty 是应用独占内存大小,包含独自分配的部分和应用进程从Zygote复制时被修改的Zygote分配的内存页。 HeapAlloc 是Dalvik堆和本地堆分配使用的大小,它的值比Pss Total和Private Dirty大,因为进程是从Zygote中复制分裂出来的,包含了进程共享的分配部分。
  • .so mmap & .dex mmap ... mmap 映射本地或虚拟机代码到使用的内存中。
  • Unknown 无法归类的其他项。主要包括大部分的本地分配。
  • Native Heap native代码申请的内存, 堆和栈,及静态代码块等。
  • TOTAL进程总使用的实际内存。
  • Objects 中显示持有对象的个数。这些数据也是分析内存泄漏的重要数据。如activity等。

多线程的应用在Android开发中是非常常见的,常用方法主要有:

  1. 继承Thread类
  2. 实现Runnable接口
  3. Handler
  4. AsyncTask
  5. HandlerThread

内部原理 = Thread类 + Handler类机制,即:

通过继承Thread类,快速地创建1个带有Looper对象的新工作线程
通过封装Handler类,快速创建Handler & 与其他线程进行通信
5. 使用步骤
HandlerThread的本质:继承Thread类 & 封装Handler类
HandlerThread的使用步骤分为5步
// 步骤1:创建HandlerThread实例对象
// 传入参数 = 线程名字,作用 = 标记该线程
   HandlerThread mHandlerThread = new HandlerThread("handlerThread");

// 步骤2:启动线程
   mHandlerThread.start();

// 步骤3:创建工作线程Handler & 复写handleMessage()
// 作用:关联HandlerThread的Looper对象、实现消息处理操作 & 与其他线程进行通信
// 注:消息处理操作(HandlerMessage())的执行线程 = mHandlerThread所创建的工作线程中执行
  Handler workHandler = new Handler( handlerThread.getLooper() ) {
            @Override
            public boolean handleMessage(Message msg) {
                ...//消息处理
                return true;
            }
        });

// 步骤4:使用工作线程Handler向工作线程的消息队列发送消息
// 在工作线程中,当消息循环时取出对应消息 & 在工作线程执行相关操作
  // a. 定义要发送的消息
  Message msg = Message.obtain();
  msg.what = 2; //消息的标识
  msg.obj = "B"; // 消息的存放
  // b. 通过Handler发送消息到其绑定的消息队列
  workHandler.sendMessage(msg);

// 步骤5:结束线程,即停止线程的消息循环
  mHandlerThread.quit();
 

猜你喜欢

转载自blog.csdn.net/zhangcanyan/article/details/84556808
RSS