Fresco 4.X和5.X内存分析

两年前部落项目接入Fresco的时候,那时候主流机型还是4.X。Fresco在4.X的机器的内存性能很好,Bitmap存在Ashmem(匿名共享内存)层里面的,对应用的内存缓存的压力不大。

4.X系统的Fresco

安卓系统的Ashmem层这里不做过多介绍,我们来看下缓存到Ashmem最后一个JAVA函数。通过注释发现,只有purgeable bitmap才能生效,我们来看下purgeable bitmap究竟是什么。

inPurgeable这个属性标识这个Bitmap是否是可清除的,设置为true之后,该系统会自动把Bitmap存储在Ashmem中, 当系统存储不足的时候会被回收,等到需要的时候,会在主线程重新进行解码,然而这种解码是会造成主线程卡顿的。

为了解决这种卡顿,Fresco调用AndroidBitmap_lockPixels这个native方法锁住这块内存,锁住这块内存之后GC便不会对该内存生效,因此就不会有在主线程重编码的卡顿问题了。Fresco需要自己进行这块内存的管理。Fresco里面只使用了pin方法,unpin操作通过Bitmap的recycle的操作来完成,如果Bitmap最后没有释放,那么会造成内存泄漏,影响系统的运行状况。所幸的是,Fresco的引用计数方式已经很完善,并且当SimpleDraweeView onDetachWindow的时候也会做释放操作,在这种情况下内存交给Fresco还是挺令人放心的。

5.X以上系统的Fresco

然而purgeable bitmap引起主线程卡顿的这一缺陷最终使得谷歌在5.0以上的系统废弃了它,所以Fresco在5.0以上系统再也没法使用Ashmem层了,Bitmap的内存压力重新回到了Java Heap中。随着主流操作系统逐渐趋向于5.0,6.0,Fresco导致的OOM问题也趋于严重。

经过对Fresco内存缓存系统的分析,我们可以看到CountingMemoryCache这个内存缓存类里面实际上是包含两块内存区域的。

mExclusiveEntries和mCacheEntries都是基础Lru策略进行存储管理,mExclusiveEntries这块存储是用来缓存没有被使用等待回收的Bitmap内存的,也就是说,如果一个Bitmap的引用计数为0,他会进入到mExclusiveEntries中,被mExclusiveEntries lru淘汰的Bitmap才会被真正的释放。

然而,坑爹的是,默认配置中对这块缓存的大小和数量限制简直可以说是没有,之前代码内限制都是Integer.MAX_VALUE,在DefaultBitmapMemoryCacheParamsSupplier这个类里面对这块内存的配置项进行限制,对5.0以上Fresco的内存优化效果巨大,目前我这里的限制是(150,17M),mCacheEntries还是保持原配置,这里需要结合具体业务进行设置。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Android机动车

热乎的大厂Android面试题(第二波)

11220
来自专栏非著名程序员

推荐几个非常有用的开发工具之Android Studio插件

推荐几个非常有用的开发工具 非著名程序员 我们都知道Eclipse开发Android将在今年年底google不再继续提供相应的开发支持,转而开始强烈发展Andr...

20380
来自专栏Python中文社区

用Python将word文件转换成html

序 最近公司一个客户大大购买了一堆医疗健康方面的科普文章,希望能放到我们正在开发的健康档案管理软件上。客户大大说,要智能推送!要掌握节奏!要深度学习!要让用户...

86670
来自专栏walterlv - 吕毅的博客

.NET 中各种混淆(Obfuscation)的含义、原理、实际效果和不同级别的差异(使用 SmartAssembly)

发布于 2018-08-19 12:42 更新于 2018-08...

41710
来自专栏程序员互动联盟

【前沿技术】使用 Go 进行 iOS 和 Android 编程

虽然 Go 并不是一门新语言,不过最近两年来 Go 还是增加了很多有趣的特性,而且使用这门语言的知名项目的数量也在快速的增长。我写过一篇文章,介绍了 SiteP...

42650
来自专栏技术记录

java-FFmpeg(一) 实现视频的转码和截图功能

FFmpeg是一个开源免费跨平台的视频和音频流方案,属于自由软件,采用LGPL或GPL许可证(依据你选择的组件)。它提供了录制、转换以及流化音视频的完整解决方...

2K80
来自专栏xingoo, 一个梦想做发明家的程序员

Spark DataFrame写入HBase的常用方式

Spark是目前最流行的分布式计算框架,而HBase则是在HDFS之上的列式分布式存储引擎,基于Spark做离线或者实时计算,数据结果保存在HBase中是目前...

1K50
来自专栏Albert陈凯

2018-10-14 Redisson项目介绍Redisson项目介绍i flym

Rui Gu edited this page <relative-time datetime="2018-05-23T22:07:43Z" title="Ma...

29730
来自专栏我就是马云飞

LiveDate和LifeRegistry的协同操作

前言 这个是Android Architecture Components(简称AAC)的第三篇,之前的两篇 文章分别介绍了Lifecycle和ViewMode...

24080
来自专栏微服务生态

Akka简单的性能测试

这种方案是采用MQ作为中间的媒介,在服务端采用线程池异步处理任务,处理完成之后将结果发送到MQ中,客户端采用侦听的方式得到结果继续进行处理。

21210

扫码关注云+社区

领取腾讯云代金券