YYCache
1. 线程安全
有多重方法可以保证线程安全。TMMemoryCache 在设计时,把所有读写操作都放到了同一个 concurrent queue 中,然后用dispatch_barrier_async 来保证任务能顺序执行,据说这种方法会有多余的线程开销。
YYCache则采用了不同的方式,在memoryCache中采用互斥锁pthread_mutex_t,在DiskCachez中用dispatch_semaphore_t的信号量来保证线程安全,信号量的值设为1,和互斥锁的效果一样。
2. MemoryCache
核心是_YYLinkedMap
有一个自己实现的双向链表,由_YYLinkedMapNode组成,用LRU算法来实现淘汰算法。Node中存储了最关键的key和value
用一个dic( 用的是coreFoundation的CFMutableDictionaryRef,
相对于Foundation.framework中的NSMutableDic,效果更高,关键更通用,不仅限于iOS.),实现了一个key和Node的哈希。同时存储了如数量限制、总容量限制、存活时间限制,作为可配置参数存在。
3. Disk Cache
将文件存储和sqlite相结合
数据小于20K存于inline_data中,大于20k,存在文件中,filename字段存储元数据,即文件名,从而实现了最高效的存储。
核心数据存储代码
- (void)setObject:(id<NSCoding>)object forKey:(NSString *)key {
if (!key) return;
if (!object) {
[self removeObjectForKey:key];
return;
}
NSData *extendedData = [YYDiskCache getExtendedDataFromObject:object];
NSData *value = nil;
if (_customArchiveBlock) {
value = _customArchiveBlock(object);
} else {
@try {
value = [NSKeyedArchiver archivedDataWithRootObject:object];
}
@catch (NSException *exception) {
// nothing to do...
}
}
if (!value) return;
NSString *filename = nil;
if (_kv.type != YYKVStorageTypeSQLite) {
if (value.length > _inlineThreshold) {
filename = [self _filenameForKey:key];
}
}
Lock();
[_kv saveItemWithKey:key value:value filename:filename extendedData:extendedData];
Unlock();
}
最后有个疑惑,读了一遍源码,在使用时是不是整个工程用一份YYCache(或者说是单例,因为内存缓存是存在YYCache的实例中的),那么这样会不会造成DishCache的customArchiveBlock有可能特别大呢