内存缓存比较
NSCache
官方提供的系统类,用法类似于字典,是一个线程安全的类,对对象是用了强引用,系统会自动的做内存管理,缺点是没法对内存中的清除策略做一定的控制。清除是按队列的方式清除 先进先出。
AFnetworikng
其中的AFAutoPurgingImageCache
类是图片缓存,里面涉及到内存缓存。
我们看其中的两个东西,一个是他的缓存的数据结构,一个是清除策略。
1 | @property (nonatomic, strong) NSMutableDictionary <NSString* , AFCachedImage*> *cachedImages; |
通过属性定义及初试化方法,我们可知,他就是一个字典,里面放了一个对象.
1 | - (void)addImage:(UIImage *)image withIdentifier:(NSString *)identifier { |
通过放入一个缓存的方法,我们可以看到他的清除策略,用的是一个GCD的栏珊函数,做到线程的依赖,来解决字典的线程不安全性,然后通过时间排序,来删除最后一个函数,知道符合内存缓存的大小限制为止。
SDWebImageView
1 | interface SDImageCache () |
从这个定义我们就可以看出 他的内存缓存AutoPurgeCache
完全是 用的是封装系统的NSCache,只是加了一个通知.
YYCache
我们再来看YYCache的
1 | @interface _YYLinkedMap : NSObject { |
可以看出_YYLinkedMap
这是一个链表,_YYLinkedMapNode
.
首先我们清楚一点,对于内存缓存的去除操作来说,我们要尽可能的快,这样我们性能才能好,而字典的去除操作是0(1),所以不管怎么变化,最终的存储都要落在字典上,但是如果只是字典,对于删除操作来说,我们需要一定的策略去清除内存,而字典是无序的,不管什么策略,肯定不是随机的,肯定是某种意义上的有序,所以,需要我们去在无序的字典中怎么去构建有序的一些东西,在AF中,我们可以看到,他给每个元素一个时间,然后将字典的所有value去排序,这样来构建一个有序,而YYCache就是通过链表的方式来构建有序。
1 | - (void)_trimToCost:(NSUInteger)costLimit { |
就是一个while循环,去清除,他这里元素用的是一个_YYLinkedMap的插入和删除遵循了LRU 队列的规则。我们可以先看清除的代码。
1 | - (_YYLinkedMapNode *)removeTailNode { |
是链表的操作,先看最后一个是不是第一个,是的话 直接置为nil就行,不是的话,将最后一个的前一个_tail->_prev
置为最后一个,然后取出最后一个的后一个_tail->_next
.
下面我们看下LRU队列相关代码
1 | - (id)objectForKey:(id)key { |
当我们访问了一个元素后,就会将这个元素放到lru队列的最前面