cover_image

浏览漫画手机发热问题追踪

侯锐 快看技术
2020年01月09日 10:51

背景

升级SDWebImage5.0后在iOS12、iOS13手机上看漫画时有明显的发热和耗电问题,影响用户体验。

需求

在漫画详情页漫画图片主要采用的是webp格式,节省流量成本,加载速度更快。
滑动浏览中设置预加载机制,通过prefetch([SDWebImagePrefetcher prefetchURLs]) + hitImageCache([SDImageCache imageFromCacheForKey])实现,减少等待时间。
通过removeImageCache等方式减少app使用运行内存过大可能导致的崩溃问题。
目前缓存和预加载均使用SDWebImage 5.0,webp编解码通过SDImageWebPCoder实现。

流程图

图片


漫画详情业务流程图

图片


图片下载完成后SDWebImage流程图

问题分析

SDWebimage 5.0 升级前无明显的发热问题,对比业务代码和SDWebImage后的几点区别:

  • SDImageWebpCoder版本不同

  • 升级前app版本限制了并发数量为3(默认为6)

  • iOS版本不同,iOS13还未发布

当前版本环境为iPhone 8P, iOS 13.3,libwebp1.0.2,SDWebImage 5.0.6, MaxConcurrentDownloads = 6, 启用预加载。
尝试控制变量法,替换方案后结合instruments打印CPU表现。(以下测试用例皆为成也萧何51话)

webpCoder

图片

SDWebImageWebPCoder(当前版本)

图片

YYImageCoder

图片

UIImage+Webp(SDImageCoder3.0)

YYImageCoder表现最好,SDWebImage3.0老版本CPU略有下降但不明显。

降低并发数

图片

MaxConcurrentDownloads = 3

图片

MaxConcurrentDownloads = 1

当并发请求数量为1时有明显改善,cpu使用率与并发数量正相关。

更新SDWebImage版本和SDWebpCoder版本

图片

SDWebImageWebPCoder 0.2.5 libwebp 1.0.3 (was 1.0.2)

图片

SDWebImage 5.4.0 (was 5.0.6)

此方法旨在排除是否为当前使用SD版本不稳定所致,无明显改善。

Instruments && Energy Logs

图片

Energy logs

[ACKComicDetailViewController hitImageCache:]
来源:Energy Logs
影响设备:9685个(排名第4),iOS 13占比 100%
版本:5.57 release
正常浏览漫画下使用Time Profiler检测

图片

Time Profiler

注释此方法后CPU表现

图片

YYImageCoder

图片

SDImageWebpCoder5.0

对比上面使用SDImageWebpCoder5.0但没有注释hitImageCache的情况(当前版本),CPU使用率依然有较大下降。
此时查看Instrument,hitimagecache消失,但decodeImage方法上升。


结论

1 hitImageCache 缓存命中方法存在问题,影响较大,主要是调用次数过多,增加无意义的解码操作。
2 webp解码存在效率问题,且在iOS13上存在严重效率问题。

解决方案

修改或替换漫画详情页中的hitImageCache逻辑

从流程图看imageFromCacheForKey和prefetchUrls/sd_setimageWithUrl 有相同的逻辑,可以尽量避免频繁调用hitImamgeCache而尽量使用prefetchUrls。

优点:逻辑更简单。
缺点:内存使用可能变高。

替换webp解码方式

优点:从解码效率上提升,图片加载更快,cpu使用更小。
缺点:可能丢失某些细节的方式换取速度和cpu使用,且YYImageCoder不再维护,再使用最新的SDWebImage 5.4.0后,有webp加载不出来的问题。

可在浏览漫画时降低图片请求的并发数量

优点:影响范围小。
缺点:未从根本上解决问题,屏幕存在多图情况下体验不好。

使用SDWebImageCacheSerializer在SDImageCache缓存前转换NSData

SDWebImage中作者说明:

  • The cache serializer is used to convert the decoded image, the source downloaded data, to the actual data used for storing to the disk cache. If you return nil, means to generate the data from the image instance, see SDImageCache.

  • For example, if you are using WebP images and facing the slow decoding time issue when later retriving from disk cache again. You can try to encode the decoded image to JPEG/PNG format to disk cache instead of source downloaded data.

由流程图可知,图片下载完成后,会异步调用[SDWebImageCacheSerializer cacheDataWithImage: originalData: imageURL:],返回自定义的Data存入磁盘。当我们实现了此协议,且在图片是webp格式且为静态图是,返回nil,SDWebImage会自动将UIImage转为png/jpeg的data(根据是否有透明像素)。本质为减少webp decoder的调用次数。
以下为转为jpeg data缓存后的CPU表现

图片

SDWebImageCacheSerializer

图片质量对比:

图片

开启SDWebImageCacheSerializer

图片

关闭SDWebImageCacheSerializer

优点:采用jpeg和png时,decoder原生支持,cpu消耗更少,只在网络下载图片后调用一次webpDecoder。
缺点:磁盘缓存变大,需要及时清理,已经使用WebP data缓存的数据不替换,只能在当前图片无磁盘缓存时生效。

关于磁盘缓存可能增大问题:
SDImageCache提供API限制磁盘缓存最大占用空间(maxDiskSize),在适当的时机主动调用deleteOldFilesWithCompletionBlock清理过期和超过最大缓存空间之外的缓存文件。

后续方向

业务:

  • 减少没有必要的解码/hitimagecache

  • Prefetch只下载不解码(是否有白屏问题)

  • 根据滚动速度调用hitimagecache

  • Hitimagecache替换为可取消的任务

图片库:

  • 调研 SDWebImageCacheSerializer 转jpeg/png 方案 (磁盘缓存清理问题)

  • 根据可用运行内存控制内存缓存


继续滑动看下一个
快看技术
向上滑动看下一个