本文来自于腾讯优测公众号(wxutest),未经作者同意,请勿转载,原文地址:https://mp.weixin.qq.com/s/8BiKIt3frq9Yv9KV5FXlGw

1.3新问题的进一步挖掘

在上一节里,我们介绍了内存测试的基本流程,讲述了如何发现并处理简单的内存问题。对于Dalvik Heap部分总结出了一些常见的问题模式,以及如何使用工具识别和处理这些常见的内存问题。

当简单问题不再是问题的时候,我们就会开始遇上一些奇怪问题了,类似于下面这些:

“我们这个版本引入了一个挺简单的库,内存就涨了2M”

“这些代码只是初始化了几个对象,还没有开始用呢”

“我只是改了一行代码,没有创建新对象”

“我一行代码都没改,怎么会涨呢”

这次出现的问题就是这样这一类问题,新版本的Dalvik Heap Pss内存出现了2M左右的增长。但Dalvik Heap Alloc只增长了273K的情况下。而从Dalvik Heap Free也能看出大部分增长的内存是空闲状态的。

经过一段时间对问题的观察,我们有以下几点发现:

  • 经过较长时间待机后也没有被释放回系统。
  • 有几处代码会导致内存增长,只要将这些代码屏蔽掉,内存情况就下降到正常水品。
  • 这些代码分配的内存并不多,甚至有些地方是不需要分配内存的。
  • 有些代码并不是这个版本新加入的,已经存在较长时间了。
  • 使用裁剪功能的方法编译并分析内存后,基本可以确定是新加入代码消耗了内存,但并没有内存泄漏,代码经过review也没有发现问题。

这个结果让我们陷入了困惑,常用的方法找不出问题,说明有更深层次的原因。接下来要从更底层的Dalvik虚拟机寻找问题。

1.3.1 Dalvik Heap内部机制

为了弄清楚为什么DVM占着内存不释放,我们阅读了DVM分配内存部分的代码。位置在Android源码的dalvik/vm/alloc下,约255K。分析出的主要流程如下:

1) DVM使用mmap系统调用从系统分配大块内存作为Java Heap。根据系统机制,如果分类的内存尚未真正使用,就不计入PrivateDirty和PSS。例如图1-8,Heap Size/Alloc很多,但大部分是共享,实际使用的较少。所以反映到PrivateDirty/PSS里的内存并不多。

图1-8 共享内存较多的进程

2) New对象之后,由于要向对应的地址写入数据,内核开始真正分配该地址对应的4K物理内存页面。

Alloc.cpp, 176行起:

图1-9 DVM虚拟机分配内存的代码

3) 运行一段时间后,开始GC,有些对象被回收了,有些会一直存在,如图1-10所示。

图1-10黑点表示的内存会被回收

4) 在GC时,有可能会进行trim。即将空闲的物理页面释放回系统,表现为PrivateDirty/PSS下降。

HeapSource.cpp, 431行:

图1-11 释放内存回系统的代码(一)

HeapSource.cpp,1304行:

图1-12 释放内存回系统的代码(二)

1.3.2 问题所在

在了解DVM分配释放内存的机制后,根据dumpsys观察到的现象,猜测可能出现了页利用率问题(页内碎片)。如图1-13所示,第一行:在开始阶段,内存分配的较满。第二行:经过GC后,大部分对象被释放,少部分留下来。

图1-13产生内存碎片

这种情况下可能会产生的问题是,整页的4K内存中可能只有一个小对象,但统计PrivateDirty/PSS时还是按4K计算。

在通常的jvm虚拟机中,有Compacting GC机制,整理内存对象,将散布的内存移动到一起。但根据DVM的代码,DVM的Mark-Sweep算法不能移动对象,即没有内存整理功能,这种情况下就会形成内存空洞。

在猜测了可能的问题后,需要验证是否如猜测原因所致,由于MAT的对象实例数据中有地址和大小信息,我们先从MAT中导出数据。

在MAT中列出所有对象实例:list_objects java.*,然后选中所有数据导出为CSV格式,如下所示:

Class Name,Shallow Heap,Retained Heap,
class java.lang.Class @ 0x41fdd1e8,16,56,
class test.bxi$3 @ 0x432501c8,0,0,
class test.aaw$c$1 @ 0x4324fef8,0,0,
class test.ds @ 0x4324fc88,8,48,
class test.bxh @ 0x4324f438,8,248,
class test.bxg @ 0x4324f248,0,0,
class test.bxd$1 @ 0x4324f028,0,0,

处理导出的csv文件,按页面进行统计,取每个对象的地址的高位(&0xfffff000),结果相同的对象处在同一页面中。最后再按每个页面所有对象的大小分类统计,做出直方图如图1-14所示。

图1-14对页面利用率进行分类统计

这张图就是被测应用的页面利用率分布图,左边是利用率低的页面,右边是利用率高的页面。如果发现利用率低的页面数目增加,说明小对象碎片的数量增加了。

1.3.3 优化Dalvik内存碎片

为了能够找出有问题的代码,我们将上一步得到的数据继续处理。取出所有使用不满2K的页面的内存块地址,再使用OQL将地址导入到MAT中,分析地址对应的对象是什么。如图1-15所示就是将地址重新导入到MAT中得到的对象列表了:

图1-15内存碎片页中的对象

在这里基本就能看出来是哪些对象造成了内存的碎片化,数量比较多的前几个类的自然嫌疑比较大,可以先对前几个类的相关代码进行分析。也可以对这些代码进行针对性的内存测试,观察内存情况。

通过对生成这些对象的代码分析和模拟实验,我们还原出问题的基本过程:

  • 生成对象过程需要较多的临时变量。
  • 批量生成过程中,由于还有空闲内存,虚拟机没有做GC。
  • 完成后才进行GC,清除了所有的零时变量,留下碎片化的内存。

下图是造成这个问题的类似代码,执行这段代码将会在内存中形成很多碎片,造成很高的PSS占用。

private Object result[] = new Object[100];
void foo() {
for(int i = 0; i < 100; ++i) {
byte[] tmp = new byte[2000];
result[i] = new byte[4];
}
}

图1-16显示了类似情况下数组的分配范围,可见数组中每个成员的内存地址都是不连续的,并且相隔很远。这种情况下就会消耗很多个物理内存页面,增加Heap Free,造成例子中的问题。

图1-16内存碎片对象地址的例子

经验小结

根据上述的流程,我们搞清楚了造成问题的原因,并且找到了问题代码。那么应当总结一些经验,以供借鉴。对于测试人员来说,有以下两个经验:

  • MAT是探索Java堆并发现问题的好帮手,能够迅速发现常见的图片和大数组等问题。但仅靠MAT提供的功能也不是万能的,比如这个问题的数据就隐藏在对象的地址中。
  • 对Android测试经验来说,可能容易找到的是应用代码及框架的各种测试经验和指导,底层以及涉及性能的测试经验并不太多。这方面可以借鉴Linux系统的测试经验,了解内核及进程相关的知识,熟悉常用工具。
  • 内存分配的最小单位是页面,通常为4K。

对于开发人员,以下两个经验也许能有帮助:

  • 尽量不要在循环中创建很多临时变量。
  • 可以将大型的循环拆散,分段或者按需执行。

更多精彩内容欢迎关注腾讯优测的微信公众账号:

腾讯优测是专业的移动云测试平台,为应用、游戏、H5混合应用的研发团队提供产品质量检测与问题解决服务。不仅在线上平台提供app自动化测试、云真机远程操控与调试、私有自动化测试工具XTest等多种质量检测工具,更为VIP客户配备了专家团队提供定制化综合测试解决方案。

【腾讯优测干货分享】如何降低App的待机内存(三)——探索内存增长的原因的更多相关文章

  1. 【腾讯优测干货分享】如何降低App的待机内存(四)——进阶:内存原理

    本文来自于腾讯优测公众号(wxutest),未经作者同意,请勿转载,原文地址:http://mp.weixin.qq.com/s/3FTPFvZRqyAQnU047kmWJQ 1.4进阶:内存原理 在 ...

  2. 【腾讯优测干货分享】如何降低App的待机内存(二)——规范测试流程及常见问题

    本文来自于腾讯优测公众号(wxutest),未经作者同意,请勿转载,原文地址:https://mp.weixin.qq.com/s/806TiugiSJvFI7fH6eVA5w 作者:腾讯TMQ专项测 ...

  3. 【腾讯优测干货分享】越用越卡为哪般——如何降低App的待机内存(一)

    本文来自于腾讯优测公众号(wxutest),未经作者同意,请勿转载,原文地址:http://mp.weixin.qq.com/s/1_FKMbi1enpcKMqto-o_FQ 作者:腾讯TMQ专项测试 ...

  4. 【腾讯优测干货分享】如何降低App的待机内存(五)——优化dex相关内存及本章总结

    本文来自于腾讯优测公众号(wxutest),未经作者同意,请勿转载,原文地址:http://mp.weixin.qq.com/s/01Abwe0p1h3WLh28Tzg_Dw 1.5案例:优化dex相 ...

  5. 【腾讯优测干货分享】安卓专项测试之GPU测试探索

    本文来自于Dev Club 开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57c7ffdc0569a1191bce8a63 作者:章未哲——腾讯SNG质 ...

  6. 【腾讯优测干货分享】Android 相机预览方向及其适配探索

    本文来自于腾讯bugly开发者社区,未经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/583ba1df25d735cd2797004d 由于Android系统的开放策略 ...

  7. 【腾讯优测干货分享】微信小程序之自动化亲密接触

    本文来自于腾讯优测公众号(wxutest),未经作者同意,请勿转载,原文地址:http://mp.weixin.qq.com/s/HcPakz5CV1SHnu-U8n85pw 导语 山雨欲来风满楼,最 ...

  8. 【腾讯优测干货分享】Android内存泄漏的简单检查与分析方法

    本文来自于Dev Club 开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57d14047603a5bf1242ad01b 导语 内存泄漏问题大约是An ...

  9. 【腾讯优测干货】看腾讯的技术大牛如何将Crash率从2.2%降至0.2%?

    小优有话说: App Crash就像地雷. 你怕它,想当它不存在.无异于让你的用户去探雷,一旦引爆,用户就没了. 你鼓起勇气去扫雷,它却神龙见首不见尾. 你告诫自己一定开发过程中减少crash,少埋点 ...

随机推荐

  1. 【原】谈谈对Objective-C中代理模式的误解

    [原]谈谈对Objective-C中代理模式的误解 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 这篇文章主要是对代理模式和委托模式进行了对比,个人认为Objective ...

  2. 首个threejs项目-前端填坑指南

    第一次使用threejs到实际项目中,开始的时候心情有点小激动,毕竟是第一次嘛,然而做着做着就感受到这玩意水好深,满满的都是坑,填都填不过来.经过老板20天惨无人道的摧残,终于小有成就. 因为第一次搞 ...

  3. 从备考PMP到与项目经理同呼吸

    前言 PMP是什么梗? 项目管理专业人士资格认证.它是由美国项目管理协会(Project Management Institute(PMI)发起的,严格评估项目管理人员知识技能是否具有高品质的资格认证 ...

  4. 【开源】.Net Api开放接口文档网站

    开源地址:http://git.oschina.net/chejiangyi/ApiView 开源QQ群: .net 开源基础服务  238543768 ApiView .net api的接口文档查看 ...

  5. hadoop2.7之Mapper/reducer源码分析

    一切从示例程序开始: 示例程序 Hadoop2.7 提供的示例程序WordCount.java package org.apache.hadoop.examples; import java.io.I ...

  6. Java 为值传递而不是引用传递

    ——reference Java is Pass by Value and Not Pass by Reference 其实这个问题是一个非常初级的问题,相关的概念初学者早已掌握,但是时间长了还是容易 ...

  7. IdentityServer4 使用OpenID Connect添加用户身份验证

    使用IdentityServer4 实现OpenID Connect服务端,添加用户身份验证.客户端调用,实现授权. IdentityServer4 目前已更新至1.0 版,在之前的文章中有所介绍.I ...

  8. c#比较两个数组的差异

    将DataTable中某一列数据直接转换成数组进行比较,使用的Linq,要引用命名空间using System.Linq; string[] arrRate = dtRate.AsEnumerable ...

  9. BPM流程中心解决方案分享

    一.需求分析 在过去办公自动化的浪潮中,很多企业已经实施了OA流程,但随着客户的发展和对流程管理的越来越重视, 客户对流程应用需求越来越深 入,您可能面临以下需求: 1.流程功能不能满足需求,包括流程 ...

  10. 基于Node.js实现一个小小的爬虫

    以前一直听说有爬虫这种东西,稍微看了看资料,貌似不是太复杂. 正好了解过node.js,那就基于它来个简单的爬虫. 1.本次爬虫目标: 从拉钩招聘网站中找出“前端开发”这一类岗位的信息,并作相应页面分 ...