如何實現(xiàn)一個Cache

引子

遇到一個需求:N多個Cell笨奠,Cell不能點擊,但是第二次出現(xiàn)到屏幕上的時候算已讀唤殴,去除NEW標志(默認有)般婆。
先分析是客戶端做還是服務(wù)端做?
很明顯是客戶端做。因為他不同于新聞的已讀朵逝,是點擊進去之后改變狀態(tài)的(新聞這個可以點擊調(diào)用接口)蔚袍,我們的坑爹需求是不點擊,展示就改變狀態(tài),那這個接口的調(diào)用就無極限了啤咽。而且我們也沒有要求不同設(shè)備同步晋辆,所以也沒有必要通知服務(wù)端。
于是在Cell出現(xiàn)的時候做這個操作宇整。

我一開始的時候在當(dāng)前頁面做一個一級緩存瓶佳,比如存儲一個字典,Value就是Yes/NO鳞青。到時候找到Key(數(shù)據(jù)的唯一ID)=對應(yīng)的Value是否YES霸饲,YES就隱藏NEW的標志。
在頁面消失之前臂拓,再做一次二級緩存厚脉,把我的字典存儲起來。

但回頭想想胶惰,為什么我要用NSDictionary器仗?因為我直覺要用,緩存表高度什么的童番,習(xí)慣用NSDictionary實現(xiàn)精钮。那么NSArray可以嗎,我可以把已經(jīng)閱讀過的ID存儲到NSArray里剃斧,到時判斷數(shù)組是否Contain這個ID來判斷轨香,那有什么區(qū)別?

NSDictionary和NSArray的區(qū)別

我的直觀感覺未驗證:NSDictionary查找Key的過程應(yīng)該并不是一個遍歷的行為幼东,每一個key應(yīng)該有一個hash臂容,查找的過程就比較方便。Key與Value的映射用到了一個HashMap根蟹。
NSArray查找是否存在這個ID脓杉,做的是一個遍歷。

回到題目上來 先比較一下系統(tǒng)的NSCache

NSDictionary和NSCache的3個常說的區(qū)別

1 NSDictionary的key必須實現(xiàn)copy简逮,NSCache沒有必要球散。那么為什么NSDictionary的key需要實現(xiàn)Copy?
我能查到的僅有資料告訴我散庶,NSDictionary內(nèi)部會將key蕉堰,copy一份,可是至今我也沒明白他內(nèi)部要這么實現(xiàn)悲龟。
2 NSDictionary不是線程安全的屋讶,而NSCache是線程安全的,這一點在我們緩存一些表高度的時候就沒有影響须教,但是如果在下載的圖片時候用到緩存皿渗,就絕對不可以用NSDictionary了。
3 NSDictionary不會清除緩存,NSCache而會乐疆。這一點下面會說到NSCache的優(yōu)點成了他被拋棄的最大缺點划乖。(是不是很有哲學(xué)意味)

“NSCache 底層并沒有用 NSDictionary 等已有的類,而是直接調(diào)用了 libcache.dylib诀拭,其中線程安全是由 pthread_mutex 完成的。另外煤蚌,它的性能和 key 的相似度有關(guān)耕挨,如果有大量相似的 key (比如 “1”, “2”, “3”, …),NSCache 的存取性能會下降得非常厲害尉桩,大量的時間被消耗在 CFStringEqual() 上筒占,不知這是不是 NSCache 本身設(shè)計的缺陷≈├纾”

NSCache的最大缺點

其實NSCache已經(jīng)很不錯翰苫,最大的缺點就是清除緩存的策略不透明,這個策略也無法從runtime中看到这橙。因此我們可以看到幾乎所有的有名的第三方都自己實現(xiàn)了自己的Cache奏窑,YYCache,SDCache等等等屈扎。

因此在不需要考慮線程安全和清除緩存的情況下我們會使用NSDictionary埃唯,在考慮的情況下往往也會自己實現(xiàn)一個Cache,所以總體上來說NSCache用的反而沒NSDictionary多鹰晨。

自己實現(xiàn)一個Cache的思路

需要改進什么墨叛?先去思考一個思路
NSCache最大的問題除了緩存的totalCostLimit自動清除緩存不可控制,還有寫入的時候由于key的原因稍微慢點模蜡。
我們需要解決的就是NSCache的基礎(chǔ)上改進這兩點漠趁。
1 自動清除緩存的最佳算法。
2 讀寫快速且線程安全忍疾。

自動清除緩存的最佳算法

大家應(yīng)該都注意到過一些桌面應(yīng)用闯传,比如360軟件管家,會提醒你什么軟件你多久沒用了卤妒,是不是需要卸載丸边,并且會將最長久沒使用的軟件放到最前面。
這其實就是一個LRU淘汰算法荚孵。
LRU(Least recently used妹窖,最近最少使用)算法根據(jù)數(shù)據(jù)的歷史訪問記錄來進行淘汰數(shù)據(jù),其核心思想是“如果數(shù)據(jù)最近被訪問過收叶,那么將來被訪問的幾率也更高”骄呼。
LFU(Least Frequently Used)算法根據(jù)數(shù)據(jù)的歷史訪問頻率來淘汰數(shù)據(jù),其核心思想是“如果數(shù)據(jù)過去被訪問多次,那么將來被訪問的頻率也更高”蜓萄。

讀寫快速且線程安全

線程安全自然要考慮到加鎖隅茎,讀寫快慢又需要考慮到鎖的性能。YYCache的鎖用的是OSSpinLock 嫉沽,作者的解釋如下

“關(guān)于鎖:

OSSpinLock 自旋鎖辟犀,性能最高的鎖。原理很簡單绸硕,就是一直 do while 忙等堂竟。它的缺點是當(dāng)?shù)却龝r會消耗大量 CPU 資源,所以它不適用于較長時間的任務(wù)玻佩。對于內(nèi)存緩存的存取來說出嘹,它非常合適。

dispatch_semaphore 是信號量咬崔,但當(dāng)信號總量設(shè)為 1 時也可以當(dāng)作鎖來税稼。在沒有等待情況出現(xiàn)時,它的性能比 pthread_mutex 還要高垮斯,但一旦有等待情況出現(xiàn)時郎仆,性能就會下降許多。相對于 OSSpinLock 來說兜蠕,它的優(yōu)勢在于等待時不會消耗 CPU 資源丸升。對磁盤緩存來說,它比較合適牺氨。

文末還有一篇對較各種鎖的性能和安全性狡耻,沒有最好的鎖,只有在不同業(yè)務(wù)場景下使用最合適的鎖猴凹。

YYCache 設(shè)計思路
深入理解 iOS 開發(fā)中的鎖
不再安全的 OSSpinLock
兩種常見的緩存淘汰算法LFU&LRU

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末夷狰,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子郊霎,更是在濱河造成了極大的恐慌沼头,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件书劝,死亡現(xiàn)場離奇詭異进倍,居然都是意外死亡,警方通過查閱死者的電腦和手機购对,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進店門猾昆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人骡苞,你說我怎么就攤上這事垂蜗】铮” “怎么了?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵贴见,是天一觀的道長烘苹。 經(jīng)常有香客問我,道長片部,這世上最難降的妖魔是什么镣衡? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮档悠,結(jié)果婚禮上廊鸥,老公的妹妹穿的比我還像新娘。我一直安慰自己站粟,他們只是感情好黍图,可當(dāng)我...
    茶點故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布曾雕。 她就那樣靜靜地躺著奴烙,像睡著了一般。 火紅的嫁衣襯著肌膚如雪剖张。 梳的紋絲不亂的頭發(fā)上切诀,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天,我揣著相機與錄音搔弄,去河邊找鬼幅虑。 笑死,一個胖子當(dāng)著我的面吹牛顾犹,可吹牛的內(nèi)容都是我干的倒庵。 我是一名探鬼主播,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼炫刷,長吁一口氣:“原來是場噩夢啊……” “哼擎宝!你這毒婦竟也來了戳表?” 一聲冷哼從身側(cè)響起滚粟,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎吩愧,沒想到半個月后顾彰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體极阅,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年涨享,在試婚紗的時候發(fā)現(xiàn)自己被綠了筋搏。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡厕隧,死狀恐怖拆又,靈堂內(nèi)的尸體忽然破棺而出儒旬,到底是詐尸還是另有隱情,我是刑警寧澤帖族,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布栈源,位于F島的核電站,受9級特大地震影響竖般,放射性物質(zhì)發(fā)生泄漏甚垦。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一涣雕、第九天 我趴在偏房一處隱蔽的房頂上張望艰亮。 院中可真熱鬧,春花似錦挣郭、人聲如沸迄埃。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽侄非。三九已至,卻和暖如春流译,著一層夾襖步出監(jiān)牢的瞬間逞怨,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工福澡, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留叠赦,地道東北人。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓革砸,卻偏偏與公主長得像除秀,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子算利,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,614評論 2 353

推薦閱讀更多精彩內(nèi)容