我們平常的iOS開發(fā)過程中湃崩,總會(huì)遇到各種需要緩存的需求,今天就來總結(jié)一下關(guān)于緩存方面的知識(shí)。
從緩存的類型上來說呀狼,通常一個(gè)緩存是由內(nèi)存緩存和磁盤緩存組成的。
內(nèi)存緩存其容量有限但是可以高速存取损离,反之磁盤緩存是一種容量大但存儲(chǔ)速率相對較慢的緩存哥艇。
蘋果也為開發(fā)者提供了一種內(nèi)存緩存方式NSCache,NSCache的API類似于NSDictionary僻澎,使用方便貌踏,在著名的AF和SDWebImage框架中被使用來進(jìn)行緩存管理。
這里要注意一下:
蘋果官方文檔提到過在系統(tǒng)內(nèi)存吃緊發(fā)出內(nèi)存警告時(shí)窟勃,NSCache會(huì)自動(dòng)釋放對象祖乳。因此通常會(huì)在
收到內(nèi)存警告時(shí)主動(dòng)調(diào)用其removeAllObjects方法來釋放對象。
NSCache是線程安全的秉氧,因此在多線程操作中眷昆,不需要對其加鎖。
NSCache的key只是對對象進(jìn)行強(qiáng)引用而不是拷貝汁咏,因此在清理時(shí)計(jì)算的大小是緩存的實(shí)際大小而不是引用的大小亚斋。
NSCache提供了NSCacheDelegate,在緩存對象即將被清理的時(shí)候(回收過程)攘滩,系統(tǒng)回調(diào)其代理方法帅刊,一般只在測試環(huán)境下調(diào)用。
提供一段簡單的代碼看下:
另外漂问,參考來自大神ibireme文章的分析:NSCache的性能和key 的相似度有關(guān)赖瞒,如果存在大量相似的key(比如"1","2","3"......)NSCache的存儲(chǔ)性能下降的會(huì)非常厲害,大量的時(shí)間被消耗在CFStringEqual()上级解。
磁盤緩存的實(shí)現(xiàn)技術(shù)大致分為三類:基于文件讀寫冒黑,基于mmap文件內(nèi)存映射,基于數(shù)據(jù)庫勤哗;
SDWebImage抡爹,TMDiskCache等緩存都是基于文件系統(tǒng)的,即一個(gè)value對應(yīng)一個(gè)文件芒划,通過文件讀寫來緩存數(shù)據(jù)冬竟,他們的性能比較相近欧穴。
FastImageCache采用的是mmap將文件映射到內(nèi)存。mmap也有缺點(diǎn):熱數(shù)據(jù)的文件不要超過物理內(nèi)存大小泵殴,不然mmap會(huì)導(dǎo)致內(nèi)存交換嚴(yán)重降低性能涮帘;另外內(nèi)存中的數(shù)據(jù)是定時(shí)flush到文件的,如果數(shù)據(jù)還未同步時(shí)程序就掛掉了就會(huì)導(dǎo)致數(shù)據(jù)錯(cuò)誤笑诅,除了這些mmap性能還是很高的调缨。
NSURLCache和faceBook的FBDiskCache都是基于SQLite數(shù)據(jù)庫的∵耗悖基于數(shù)據(jù)庫的緩存可以很好的元數(shù)據(jù)弦叶,擴(kuò)展方便,數(shù)據(jù)統(tǒng)計(jì)速度快妇多,也很容易實(shí)現(xiàn)LRU或其他淘汰算法伤哺,但讀寫性能取決于數(shù)據(jù)大小,當(dāng)單條數(shù)據(jù)小于20k時(shí)者祖,數(shù)據(jù)越小SQLite讀取性能越好立莉,單條數(shù)據(jù)大于20k時(shí),直接寫文件的速度會(huì)更快七问。
備注:
關(guān)于OSSpinLock自旋鎖:性能最高的鎖蜓耻,原理很容易理解,就是一直忙等(dowhile)械巡,但等待時(shí)會(huì)消耗大量CPU資源媒熊,所以它不適用于較長時(shí)間的任務(wù),但是對于內(nèi)存緩存的存取來說它非常合適坟比。
dispatch_semaphore是信號(hào)量芦鳍,當(dāng)信號(hào)總量設(shè)為1時(shí)也可以當(dāng)做鎖來用。在沒有等待情況出現(xiàn)時(shí)葛账,它的性能比pthread_mutex還高柠衅,一旦有等待情況出現(xiàn)時(shí),其性能就會(huì)下降很多籍琳。相對于OSSpinLock來說菲宴,它的優(yōu)勢在于等待時(shí)不會(huì)消耗CPU資源,對于磁盤緩存來說它比較合適趋急。