升级SDWebImage5.0后在iOS12、iOS13手机上看漫画时有明显的发热和耗电问题,影响用户体验。
在漫画详情页漫画图片主要采用的是webp格式,节省流量成本,加载速度更快。
滑动浏览中设置预加载机制,通过prefetch([SDWebImagePrefetcher prefetchURLs]) + hitImageCache([SDImageCache imageFromCacheForKey])实现,减少等待时间。
通过removeImageCache等方式减少app使用运行内存过大可能导致的崩溃问题。
目前缓存和预加载均使用SDWebImage 5.0,webp编解码通过SDImageWebPCoder实现。
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话)
YYImageCoder表现最好,SDWebImage3.0老版本CPU略有下降但不明显。
当并发请求数量为1时有明显改善,cpu使用率与并发数量正相关。
此方法旨在排除是否为当前使用SD版本不稳定所致,无明显改善。
1 hitImageCache 缓存命中方法存在问题,影响较大,主要是调用次数过多,增加无意义的解码操作。
2 webp解码存在效率问题,且在iOS13上存在严重效率问题。
从流程图看imageFromCacheForKey和prefetchUrls/sd_setimageWithUrl 有相同的逻辑,可以尽量避免频繁调用hitImamgeCache而尽量使用prefetchUrls。
优点:逻辑更简单。
缺点:内存使用可能变高。
优点:从解码效率上提升,图片加载更快,cpu使用更小。
缺点:可能丢失某些细节的方式换取速度和cpu使用,且YYImageCoder不再维护,再使用最新的SDWebImage 5.4.0后,有webp加载不出来的问题。
优点:影响范围小。
缺点:未从根本上解决问题,屏幕存在多图情况下体验不好。
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表现
图片质量对比:
优点:采用jpeg和png时,decoder原生支持,cpu消耗更少,只在网络下载图片后调用一次webpDecoder。
缺点:磁盘缓存变大,需要及时清理,已经使用WebP data缓存的数据不替换,只能在当前图片无磁盘缓存时生效。
关于磁盘缓存可能增大问题:
SDImageCache提供API限制磁盘缓存最大占用空间(maxDiskSize),在适当的时机主动调用deleteOldFilesWithCompletionBlock清理过期和超过最大缓存空间之外的缓存文件。
减少没有必要的解码/hitimagecache
Prefetch只下载不解码(是否有白屏问题)
根据滚动速度调用hitimagecache
Hitimagecache替换为可取消的任务
调研 SDWebImageCacheSerializer 转jpeg/png 方案 (磁盘缓存清理问题)
根据可用运行内存控制内存缓存