缓存那些事 iOS
目前github上比较好的缓存库有如下这些
OC:
TMCache:star较多,但是目前已不再维护。
PINCache: 它是针对TMCache的改良版,解决了block过度使用造成的死锁等问题。它采用key/value形式存储一些耗时重新获取的临时对象。比如下载的数据。有内存缓存和磁盘缓存两种。采用GCD安全的从多线程获取数据。PINMemoryCache 会清空当收到内存警告或者app进入后台的时候。而在PINDiskCache当中的缓存会一直存在除非你自己减少缓存或者手动设置最大容量和期限。使用锁来保护读写操作。磁盘缓存采用的是归档操作,所以对自定义的对象必须实现NSCoding协议。使用 dispatch_semaphore 来保证线程安全,但去掉了dispatch_barrier_async,避免了线程切换带来的巨大开销,也避免了可能的死锁。
- LRU: 缓存支持 LRU (least-recently-used) 淘汰算法。
- 缓存控制: 支持多种缓存控制方法:总数量、总大小、存活时间、空闲空间。
- 兼容性: API 基本和
NSCache
保持一致, 所有方法都是线程安全的。 - 内存缓存
- 对象释放控制: 对象的释放(release) 可以配置为同步或异步进行,可以配置在主线程或后台线程进行。
- 自动清空: 当收到内存警告或 App 进入后台时,缓存可以配置为自动清空。
- 存储的单元是_YYLinkedMapNode,除了key和value外,还存储了它的前后Node的地址_prev,_next.整个实现基于_YYLinkedMap,它是一个双向链表,除了存储了字典_dic外,还存储了头结点和尾节点.它实现的功能很简单,就是:有新数据了插入链表头部,访问过的数据结点移到头部,内存紧张时把尾部的结点移除.就这样实现了淘汰算法.因为内存访问速度很快,锁占用的时间少,所以用的速度最快的OSSpinLockLock。缓存内部用双向链表和 NSDictionary 实现了 LRU 淘汰算法。
- 磁盘缓存
- 可定制性: 磁盘缓存支持自定义的归档解档方法,以支持那些没有实现 NSCoding 协议的对象。
- 存储类型控制: 磁盘缓存支持对每个对象的存储类型 (SQLite/文件) 进行自动或手动控制,以获得更高的存取性能。
- 采用的是文件和数据库相互配合的方式.有一个参数inlineThreshold,默认20KB,小于它存数据库,大于它存文件.能获得效率的提高.key:path,value:cache存储在NSMapTable里.根据path获得cache,进行一系列的set,get,remove操作更底层的是YYKVStorage,它能直接对sqlite和文件系统进行读写.每次内存超过限制时,select key, filename, size from manifest order by last_access_time desc limit ?1会根据时间排序来删除最近不常用的数据.硬盘访问的时间比较长,如果用OSSpinLockLock锁会造成CPU消耗过大,所以用的dispatch_semaphore_wait来做.
由于OSSpinLock不再安全,作者进行了修改YYMemoryCache用到了pthread_mutex_t,而YYDiskCache使用的锁是dispatch_semaphore_t。
针对YYCache和PinCache的对比文章参考:http://www.cnblogs.com/whoislcj/p/6429108.html 讲解很详细
SWIFT:
AwesomeCache: AwesomeCache 是没有明确区分 Memory 和 Disk 的,并且功能比较少。AwesomeCache 将数据存在NSCache和利用归档存在磁盘中。当获取数据时,先看本地缓存中有没有,没有就从磁盘中获取。需要从磁盘中移除所有的过期的对象。使用Dispatch Barrier确保在队列中的Block同时只有一个执行, 采用同步操作,sync则会阻塞后续代码的执行,会在barrier标识的block执行完成后才会插入新的任务到队列中。针对disk的操作都是采用的这种开辟新线程同步阻塞后续代码插入新任务到队列。
由于内存缓存使用的NSCache,下面主要介绍一下NSCache。 NSCache 是苹果提供的一个简单的内存缓存,它有着和 NSDictionary 类似的 API,不同点是它是线程安全的,并且不会 retain key。NSCache 底层并没有用 NSDictionary 等已有的类,而是直接调用了 libcache.dylib,其中线程安全是由 pthread_mutex 完成的。另外,它的性能和 key 的相似度有关,如果有大量相似的 key (比如 “1”, “2”, “3”, …),NSCache 的存取性能会下降得非常厉害,大量的时间被消耗在 CFStringEqual() 上。
- 采用swift 4
Codable。任何遵循Codable的都可以很容易的被保存和加载通过
Storage
. - 默认磁盘缓存。可选择的使用
memory storage以实现磁盘和内存缓存。
- 多种选择通过
DiskConfig
和MemoryConfig
. - 支持到期,可以清空到期对象。
- Thread safe. Operations can be accessed from any queue.
- Sync by default. Also support Async APIs.
- 通过ImageWrapper存储图片。
- 广泛的单元测试覆盖和很棒的文档。
内存缓存使用NSCache, 磁盘缓存使用文件管理。
线程安全: 使用dispatch_semaphore_t 和 DISPATCH_QUEUE_CONCURRENT。 线程安全并且无死锁。
LRU: 通过双向链表实现LRU(最近最少使用)算法。 可以通过限制容量,过期时间和内存使用情况来清除最近最少使用的对象。
支持同步和异步操作。
实现swift特性 SequenceType 和
Generator,支持
subscrip
(for ... in,
map,
flapmap,
filter
...)