性能优化的终极目标-内存简析

性能优化的终极目标-内存简析

通常来说为了避免磁盘I/O问题,都会用内存缓存起来,结果什么都用内存缓存起来,App的常驻内存就会很大,若内存处理不当机会变成内存问题,甚至最后成为OOM的导火索。

Out of Memory,OOM是常见的内存溢出问题。通常会在decode图片的时候触发,但不一定是decode图片的问题,因为也许它只是压垮骆驼的稍微大一点的稻草。在虚拟机的Heap内存使用超过堆内存最大值(Max Memory Heap)的时候,就会出现OOM问题了。

Android没有虚拟内存,安卓系统对于每个应用都有内存使用的限制,所以系统为每个应用分配一小部分内存。假如是游戏类型软件这种消耗内存的特殊应用,Android在mainifest里面可以设置LargerHeap为true。
heapsize是在manifest中设置了largeHeap=true之后,可以使用最大内存值。设置largeHeap的确可以增加内存的申请量。但不是系统有多少内存就可以申请多少,而是由dalvik.vm.heapsize限制。在内存稀缺的背景下,为了保证前台App和系统能够稳定运行,在手机剩余内存低于内存警戒线时,会触发Low Memory Killer机制,App占用的内存越多,被Low memory Killer 处理掉的机会越大。

内存问题主要包括常驻问题(如图片缓存)、内存泄露问题(如activity泄露)、GC问题(关键是GC For Alloc),后果就是导致App Crash、闪退、后台被杀、卡顿,而且这是各种资源类性能问题积压的最后一环。

  1. GC(Garbage Collection)
    最简单的的理解就是没有被GC ROOT间接或直接引用的对象的内存会被回收。当并发执行GC的时候ART比Dalvik少了一个stop-the-world的阶段,因此Dalvik比ART(Android Runtime 是Android4.4发布的用来替换Dalvik虚拟机)更容易产生Jank(卡顿)。然而在内存不足以分配给新的对象时时触发GC for Alloc,无法并发执行GC导致stop-the-world的时间会变得更长。所以尽量避免CG For Alloc,除了减少内存的申请回收外,更重要的是减少常驻内存和避免内存泄露。
  2. 内存泄露-主要指activity泄露
    因为activity对象会间接或者直接引用View、Bitmap等,所以一旦无法释放,会占用大量内存。泄露基本上都是GC ROOT 对Activity的直接引用、this$0 间接引用、mContext间接引用。
引用的方式/GC ROOTClass-(静态变量)活着的线程
mContext间接引用静态View,InputMethodManagerSensorManager、WiFiManager(其他Service进程都可以)
this$0 间接引用内类引用匿名类/Timer/TimerTask/Handler
直接引用静态Activity
  1. 图片缓存
    建议使用一个进程所能申请的最大内存的四分之一作为图片缓存(Android进程都有最大内存上限,这依据手机ROM而定,手机出厂就被固定,一般不会更改)。图片缓存达到容积上限时,内部使用LRU算法做淘汰,淘汰那些“有老有少被使用到”的图片,这就是内存图片缓存的大体设计思维。对于多图片类App,内存使用够呛,现有两种硬盘缓存方案。
    • DiskLruCache,简单理解就是LruCache的硬盘版本,容错性强,但是对比BlobCache,I/O性能一般。
    • BlobCache,这个方案源自Android原生的相册,利用索引(Index)文件、活动(Active)文件、非活动(Unactive)文件,通过索引(偏移)来读取活动文件的图片缓存。清楚旧图片的方法简单粗暴,直接seek到文件头部,覆盖写入就可以。这一切都是为了用最小的磁盘I/O代价完成磁盘缓存。
    • 另外官方也建议把内存淘汰的图片,降低压缩比存储到本地,以备后用,最大限度地降低以后复用时的解码开销。

检测Android关于内存的工具有不少,灵活的选择工具就显得特别重要,下一篇就重点介绍相关检测工具。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值