iOS缓存浅析

#了解NSDictionary和NSCache的区别,延伸到SDWebImageCahce和YYCache(个人倾向YYCache)

NSDictionary和NSCache最大的区别是:
 1、NSCache线程安全的(内部使用互斥锁实现)
 2、NSCache会自动释放内部数据(收到内存警告会立即释放)
 3、NSCache的key不必遵守NSCopy协议
 4、NSCache内部未使用NSFoundation已有类,使用的是libcache.dylib。

所以自己实现简单的缓存策略,在NSDictionary和NSCache间 还是选择NSCache。

当然NSCache也有缺点,网上的说法(未测试)当key相似度较高时,存取速度急剧下降。缓存释放策略不太好。

SDWebImageCahce原理:
内部维护一个NSCache的子类和文件系统,以图片URL为KEY,维护硬盘和NSCache子类中的缓存。在硬盘读写时,会比较耗时,所以使用队列来保证顺序执行,用NSOperation来做取消,另外还使用到了autoreleasepool,可以让内存在出autoreleasepool时释放(更快释放内存),这在YYCache中也用到了,以后快速释放内存的需求 可以借鉴。
SDWebImageCahce在加载图片的过程:
先在内存维护的NSCache子类中进行寻找,找到就返回;
内存中未找到去硬盘中找,找到,将图片存到内存中后返回,
硬盘中也未找到,就发起网络请求,请求成功后,将数据存到内存和硬盘,返回图片
网络请求失败,标记失败URL,返回nil

YYCache
内存缓存未使用NSCache及其子类,而是利用互斥锁、CFDictionary、双向链表来实现内存缓存。这样可以很好的实现内存释放策略,查找数据利用CFDictionary的key-value,双向链表来维护最近使用的顺序。
硬盘缓存使用sqlite和文件系统来实现,据说经测试小于20K的数据,存数据库比存文件速度快,大于20K反之。所以YYCache采用了两者结合的方式。大于20K的文件也会记入数据库,只是不会将实际数据写入数据库,会存入文件的URL。在sql数据库里以key为索引,增加查询速度。另外硬盘缓存YYCache使用信号量来保证线程安全。最后再提一下,它的实例对象释放,它可以在自定的释放队列异步释放对象,这样可以降低目标队列的压力(一般是主队列)。
数据加载过程和SD类似,只是存取的目标有点差别。

所以综合对比,YYCache比SD要优秀,优点:1、更好的缓存释放策略;2、更好的存取速度

再提一下,早期的YYCache使用自旋锁来实现内存缓存的线程安全,但是后来自旋锁不在安全,所以后来改成了互斥锁。

OSSpinLock问题:
如果一个低优先级的线程获得锁并访问共享资源,这时一个高优先级的线程也尝试获得这个锁,它会处于 spin lock 的忙等状态从而占用大量 CPU。此时低优先级线程无法与高优先级线程争夺 CPU 时间,从而导致任务迟迟完不成、无法释放 lock。这并不只是理论上的问题,libobjc 已经遇到了很多次这个问题了,于是苹果的工程师停用了 OSSpinLock。

你可能感兴趣的:(iOS开发)