Cocoa 拾遺 —— NSCache

Cache 的發(fā)音是 [k??]坡疼,但我還是覺得讀成“卡車”比較有愛驾诈。
這次的主角是 NSCache

緩存導(dǎo)致的問題

使用內(nèi)存緩存的好處不言而喻,但無盡地消耗內(nèi)存肯定有問題的案铺。占用過多的內(nèi)存以至于沒有更多空閑內(nèi)存供其他應(yīng)用使用蔬芥,頁面置換頻頻發(fā)生對(duì)性能的影響是不小的。

NSCache 作為內(nèi)存緩存

NSCacheNSMutableDictionary 非常相似控汉,同樣是存儲(chǔ)鍵值對(duì)但 NSCache 不需要拷貝 key笔诵。文檔說 NSCache是 “reactive cache”,當(dāng)內(nèi)存充裕時(shí)能緩存數(shù)據(jù)姑子,內(nèi)存不足時(shí)又能自動(dòng)地丟棄一些數(shù)據(jù)乎婿,但就是沒提到丟棄的規(guī)則是什么。

不過 NSCache 的提供兩個(gè)方法去限制緩存:一個(gè)是 -setCountLimit:街佑,設(shè)置緩存對(duì)象的最大數(shù)量谢翎,根據(jù)我的觀察(存疑),在對(duì)象數(shù)量到達(dá)極限后加入新對(duì)象沐旨,需要被丟棄的對(duì)象按照 LRU(Least Recently Used)規(guī)則被丟棄掉森逮。

另一個(gè) -setTotalCostLimit: 設(shè)置緩存最大的開銷。cache 在 -setObject:forKey:cost: 的時(shí)候磁携,可以為每個(gè)緩存對(duì)象設(shè)置開銷褒侧。當(dāng) cache 中所有對(duì)象的開銷之和達(dá)到閾值時(shí),cache 會(huì)丟棄數(shù)據(jù)讓開銷的總量回落閾值谊迄。開始我以為引入 cost 這個(gè)概念是為了在丟棄緩存的時(shí)候闷供,優(yōu)先把開銷大的數(shù)據(jù)扔掉,在 cache 中盡量留著盡量多的數(shù)據(jù)统诺,結(jié)果還是 LRU歪脏。

簡(jiǎn)言之,項(xiàng)目中用 NSMutableDictionary 對(duì)象做緩存的都換為 NSCache 會(huì)比較好好粮呢,畢竟能自動(dòng)丟棄唾糯。

使用 Purgeable 內(nèi)存

當(dāng)應(yīng)用申請(qǐng)一塊內(nèi)存時(shí),倘若系統(tǒng)發(fā)現(xiàn)沒用更多的空閑內(nèi)存鬼贱,那么需要將已用內(nèi)存中的數(shù)據(jù)置換到磁盤上移怯,這樣就有了內(nèi)存可供使用。但如果該內(nèi)存被標(biāo)記為 purgeable(可清除的)这难,那么內(nèi)存中的數(shù)據(jù)就會(huì)直接被丟棄舟误。而這個(gè)機(jī)制是對(duì)于那些 “創(chuàng)建開銷” 小于 "頁面置換開銷" 的對(duì)象是有益的。

類似于線程中的同步機(jī)制姻乓,purgeable 的內(nèi)存訪問也需要一套 locking mechanism嵌溢,在這樣的一個(gè)機(jī)制中有 counter 這樣的概念眯牧,指示著對(duì)象的生命周期:

  1. 當(dāng) counter >= 1, 對(duì)象可以被使用赖草;
  2. 當(dāng) counter == 0学少,對(duì)象的就可以丟棄。

NSPurgebleData 是一個(gè)遵循 NSDiscardabelContent 協(xié)議的類秧骑,作為使用 Purgeable 內(nèi)存的實(shí)現(xiàn)版确,通過 begin/endContentAccess 控制 counter,需要注意以下幾點(diǎn):

  1. -beginContentAccess 讓 counter++乎折;
  2. -endContentAccess 讓 counter--绒疗;
  3. 當(dāng) counter >= 1 時(shí)才能訪問對(duì)象占用的內(nèi)存;
  4. 只有在對(duì)象的 counter == 0 時(shí)骂澄,發(fā)送 -discardContentIfPossible 消息才釋放內(nèi)存吓蘑,否則啥也不做。

下面的代碼表示了 NSPurgeableData 的簡(jiǎn)單使用坟冲,抄自 WWDC 2013, Session 704磨镶。

// 初始化完成 counter == 1
 NSPurgeableData * purgeabelData = [[NSPurgeableData alloc] initWithBytes:fileBytes length:fileLen];

// 不需要使用數(shù)據(jù)時(shí)發(fā)送 endContentAccess 消息,counter == 0
[purgeabelData endContentAccess];

// 一段時(shí)間之后

// 發(fā)送 beginContentAccess 以獲取數(shù)據(jù)健提,
// 如果返回 NO棋嘲,則說明在內(nèi)存緊張時(shí),
// 這個(gè)對(duì)象指向的內(nèi)存釋放矩桂,需要重新生成沸移。
// counter == 1
if ([purgeabelData beginContentAccess] == NO) { 
    purgeabelData = [[NSPurgeableData alloc] initWithBytes:fileBytes length:fileLen];
}

// 結(jié)束對(duì)對(duì)象的存取, counter == 0
[purgeabelData endContentAccess];

混合使用

NSPurgeableData 不是必須和 NSCache 搭配使用,不過前面的 WWDC 的 session 和文檔中都有提到這一用法侄榴。NSCache 緩存可丟棄對(duì)象雹锣,如 NSPurgeableData,會(huì)形成 NSCache --> NSPurgeableData --> Purgeable Memory Region 這樣的關(guān)系鏈癞蚕,當(dāng) NSPurgeableData 指向的內(nèi)存中數(shù)據(jù)被丟棄時(shí)候蕊爵,cache 中的 NSPurgeableData 也會(huì)被移除。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末桦山,一起剝皮案震驚了整個(gè)濱河市攒射,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌恒水,老刑警劉巖会放,帶你破解...
    沈念sama閱讀 211,743評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異钉凌,居然都是意外死亡咧最,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來矢沿,“玉大人滥搭,你說我怎么就攤上這事〉肪ǎ” “怎么了瑟匆?”我有些...
    開封第一講書人閱讀 157,285評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)栽惶。 經(jīng)常有香客問我愁溜,道長(zhǎng),這世上最難降的妖魔是什么媒役? 我笑而不...
    開封第一講書人閱讀 56,485評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮宪迟,結(jié)果婚禮上酣衷,老公的妹妹穿的比我還像新娘。我一直安慰自己次泽,他們只是感情好穿仪,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,581評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著意荤,像睡著了一般啊片。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上玖像,一...
    開封第一講書人閱讀 49,821評(píng)論 1 290
  • 那天紫谷,我揣著相機(jī)與錄音,去河邊找鬼捐寥。 笑死笤昨,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的握恳。 我是一名探鬼主播瞒窒,決...
    沈念sama閱讀 38,960評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼乡洼!你這毒婦竟也來了崇裁?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,719評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤束昵,失蹤者是張志新(化名)和其女友劉穎拔稳,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體锹雏,經(jīng)...
    沈念sama閱讀 44,186評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡壳炎,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,516評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片匿辩。...
    茶點(diǎn)故事閱讀 38,650評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡腰耙,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出铲球,到底是詐尸還是另有隱情挺庞,我是刑警寧澤,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布稼病,位于F島的核電站选侨,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏然走。R本人自食惡果不足惜援制,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,936評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望芍瑞。 院中可真熱鬧晨仑,春花似錦、人聲如沸拆檬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽竟贯。三九已至答捕,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間屑那,已是汗流浹背拱镐。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留持际,地道東北人痢站。 一個(gè)月前我還...
    沈念sama閱讀 46,370評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像选酗,于是被迫代替她去往敵國(guó)和親阵难。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,527評(píng)論 2 349

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理芒填,服務(wù)發(fā)現(xiàn)呜叫,斷路器,智...
    卡卡羅2017閱讀 134,633評(píng)論 18 139
  • 轉(zhuǎn)自:http://southpeak.github.io/blog/2015/02/11/nscache/?ut...
    RealSlimAlan閱讀 605評(píng)論 0 1
  • 應(yīng)用場(chǎng)景: iOS中需要頻繁讀取的數(shù)據(jù)殿衰,都可以用NSCache把數(shù)據(jù)緩存到內(nèi)存中提高讀取性能朱庆。 正文: 一:定義 ...
    謝謝生活閱讀 7,152評(píng)論 6 14
  • 構(gòu)建緩存時(shí)選用 NSCache 開發(fā) Mac OS X 或 iOS 應(yīng)用程序時(shí),經(jīng)常會(huì)遇到一個(gè)問題,那就是從網(wǎng)上下...
    dingzhijie閱讀 562評(píng)論 0 2
  • 我覺得《銷售就是要搞定人》這本銷售書還不錯(cuò)。我們做銷售的,需要多讀點(diǎn)書,豐富自己的知識(shí)量闷祥。 《銷售就是要搞定人》電...
    716小飛哥閱讀 2,510評(píng)論 0 0