NSCache的缓存策略探究

网上讲NSCache的文章不少。从其他文章总结下来NSCache主要有以下几个特点:

1.NSCache是苹果官方提供的缓存管理类,在使用上类似NSMutableDictionary。因为其使用方便,很多第三方库都在使用它。比如SDWebImage和AFNetWorking。
2.NSCache会在内存低时自动释放对象。
3.NSCache是线程安全的,在进行多线程操作是,不需要再对其加锁。
4.NSCache的Key只是对对象进行了Strong引用,而非拷贝。NSCache中的key不需要实现copy。

但是网上的文章很少讲到NSCache的具体缓存策略。NSCache有两个重要的参数:

@property NSUInteger totalCostLimit;    // limits are imprecise/not strict
@property NSUInteger countLimit;    // limits are imprecise/not strict

countLimit也就是数量限制就不多说了,我想重点说的是totalCostLimit。
totalCostLimit也就是总的代价限制,调用这个方法可以设置cost

- (void)setObject:(ObjectType)obj forKey:(KeyType)key cost:(NSUInteger)g;

这里的cost也就是代价可以根据你的喜好来定义,比如你可以把缓存文件的大小作为,又或者下载某一个文件所需要的时间作为cost。这在你实际的项目中根据实际情况而定。
在我的项目中,有一个页面是视频的feed流,这里就用到了NSCache。
如果简单的实现就是用countLimit等于50来限制视频缓存的总数量不超过50条。但是更合理的方法是把每一条视频的大小作为cost,把最大内存100MB作为totalCostLimit。
当NSCache调用setObject方法时,如果已经缓存的数据已经快接近totalCostLimit了怎么办呢?它会移除哪一条已经缓存的数据来为新的数据腾空间呢?

我做了一个实验,发现NSCache的缓存策略如下:

当加入一个新的缓存之后总的cost大于totalCostLimit时,NSCache会按照加入缓存的先后顺序一个一个移除已有的缓存,直到能够放下新的缓存数据。

以下是我实验过程,不想看可以直接跳过,记着上面的结论就ok了:

- (void)addCache
{
    _cache = [[NSCache alloc] init];
    _cache.totalCostLimit = 5;
    _cache.delegate = self;

    NSString* str = [NSString stringWithFormat:@"数据cost1-order1"];
    [_cache setObject:str forKey:@(1) cost:1];
    NSLog(@"缓存数据:%@",str);
    
    str = [NSString stringWithFormat:@"数据cost2-order1"];
    [_cache setObject:str forKey:@(2) cost:2];
    NSLog(@"缓存数据:%@",str);
    
    str = [NSString stringWithFormat:@"数据cost1-order2"];
    [_cache setObject:str forKey:@(3) cost:1];
    NSLog(@"缓存数据:%@",str);
    
    str = [NSString stringWithFormat:@"数据cost3-order1"];
    [_cache setObject:str forKey:@(4) cost:3];
    NSLog(@"缓存数据:%@",str);
    
    str = [NSString stringWithFormat:@"数据cost3-order2"];
    [_cache setObject:str forKey:@(5) cost:3];
    NSLog(@"缓存数据:%@",str);
}

- (void)cache:(NSCache *)cache willEvictObject:(id)obj
{
    NSLog(@"释放缓存数据:%@",obj);
}

最后输出如下:

11.png

当NSCache 里的缓存cost总数位4的时候再插入一个cost为3的数据,首先移除了数据cost1-order1和数据cost2-order1两个数据。此时剩余:数据cost1-order2和数据cost3-order1,再次插入数据cost3-order2前,把数据cost1-order2和数据cost3-order1都移除了。

由此可见,对于NSCache的使用比较合理的方式,应该是尽量先放入cost下的缓存后放入大的数据

你可能感兴趣的:(NSCache的缓存策略探究)