SDWebImage内存爆增问题及Image解压缩

前言

在一次偶然Feed流开发,出现滑动视图后内存爆增并且退出Feed界面内存没有被回收的问题。

image

分析定位

用instrument定位到的内存增长点

- (nullable UIImage *)sd_decompressedImageWithImage:(nullable UIImage *)image
image

定位到SDWebImage在对图片进行解压缩的时候内存爆增,但是从代码中看CreateRealse配对使用,看起来也没什么问题,那就应该不是内存泄漏了,应该是这几行代码在执行过程中产生的内存消耗,但是为什么消耗这么大???

补充知识:图片解压缩

图片加载过程

在说图片解压缩之前,先说说从磁盘加载一张图片并显示到屏幕上的步骤:

  1. 使用+imageWithContentsOfFile:从磁盘中加载一张图片,这时候这张图片并没有解压缩
  2. 将UIImage赋值给UIImageView
  3. 接着一个隐式的CATransition捕获到了UIImageView图层数的变化
  4. 在主线程的下一个runloop到来时,Core Animation提交了这个隐式过渡
    • 4.1 分配内存缓存区用于管理文件IO和解压操作
    • 4.2 将文件数据从磁盘读取到内存中
    • 4.3 将压缩的图片数据解码成未压缩的位图形式,这是个非常耗时的CPU操作
    • 4.4 最后Core Animation使用未压缩的位图数据渲染UIImageView涂层

上面的步骤,将压缩的图片进行解压缩时非常耗时的CPU操作,并且这个操作默认是在主线程执行,因此在需要加载多张大图的时候,就会造成严重的性能问题,比如卡顿。

图片解压缩的必要性

既然图片解压缩这么耗性能,我们可不可以不做呢?⚠️当然不能!

在研究为什么不可以不做图片解压缩操作之前,先了解下什么是位图:

苹果官方定义:
A bitmap image (or sampled image) is an array of pixels (or samples). Each pixel represents a single point in the image. JPEG, TIFF, and PNG graphics files are examples of bitmap images.

位图图像(或者采样图像)是像素(或者样本)的数组。每个像素代表图像中的单个点。JPEG、TIFF和PNG文件都是位图图像的例子。

我们知道,不管是JPEG还是PNG,都是一种压缩的位图图形格式。只不过PNG是无损压缩,支持alpha通道,而JPEG是有损压缩,可以指定压缩比例(0-100%)。

因此,在将磁盘中的图片渲染到屏幕之前,必须先要得到原始像素数据,才能执行后续绘制操作,这就是为什么图片解压缩操作不可省略。

继续内存问题

A: 如何解决主线程进行解压缩导致的卡顿等问题?
Q: 将解压缩提前在后台线程执行掉,然后CGContextDrawImage() 绘制到画布中,将生成的图片存到缓存中,从而避免让系统区做额外的解压缩操作。这也是SDWebImage的底层实现。

但是既然这么做是为了优化性能问题,那为什么又会存在严重的内存问题呢??

在SDWebImage的issue中有相关的讨论:

harishkashyap commented on Dec 23, 2014
Its the memory issue again. decodedImageWithImage takes up huge memory and causes the app to crash. I have added an option to put this off in the library but defaulting to YES so there aren't any breaking changes. If you put off the decodeImageWithImage method in both image cache and image downloader then you shouldn't be seeing the VM: CG Raster data on the top consuming lots of memory
decodeImageWithImage is supposed to decompress images and cache them so the loading on tableviews/collectionviews become better. However, with large set of images being loaded, the experience worsened and the memory of uncompressed images even with thumbnails can consume GBs of memory. Putting this off only improved performance.

这个讨论中提到,-decodeImageWithImage这个方法用于将图片进行解压缩并缓存起来,以保证tableviews/collections交互流畅。但是如果加载高分辨率的图的话会适得其反,造成庞大的内存消耗。

CGBitmapContextCreate创建位图方法,每一个像素点都会分配一个空间来存储相关值,高分辨率的图像素点就多,也就需要分配更多的空间。这就是为什么解压缩操作会造成内存飙升。

而且在图片解压缩后,App第一次退到后台或者收到内存警告时,该图片的缓存才会被清空,其他情况会一直存在于全局缓存中。

解决方案

  1. 按需开启和关闭shouldCacheImagesInMemory
  2. 设置maxMemoryCost
  3. 手动调用-clearMemory方法
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269