MMKV_mmkv之基本介绍
MMKV淺析
? MMKV 是微信開源的一個基于 mmap 內(nèi)存映射的 key-value 組件,底層序列化/反序列化使用 protobuf 實現(xiàn),性能高,穩(wěn)定性強(qiáng)。微信團(tuán)隊為了發(fā)現(xiàn)記錄特殊文字引起微信 iOS 系統(tǒng)的 crash,在關(guān)鍵代碼前后進(jìn)行計數(shù)器的加減,通過檢查計數(shù)器的異常,來發(fā)現(xiàn)引起閃退的異常文字,但同時因為諸多cell的復(fù)雜頁面情境下希望新加的計時器不會影響性能,另外這些計數(shù)器需要永久存儲下來——因為閃退隨時可能發(fā)生,所以亟需高性能的通用 key-value 存儲組件,而微信團(tuán)隊在實時寫入和高性能的選擇標(biāo)準(zhǔn)下,通過對比NSUserDefaults、SQLite 等常見組件,最終選擇了mmap 內(nèi)存映射文件,并將其封裝成為了MMKV組件。下面我們來逐步進(jìn)行了解
1.mmap簡介
? 認(rèn)真分析mmap:是什么 為什么 怎么用這篇文章講的炒雞詳細(xì),很佩服作者,本人也不想ctrl+c/v一遍, 。但在此處總結(jié)下:
mmap實現(xiàn)了一種使用內(nèi)存映射到磁盤文件的方法,將本該屬于磁盤文件的對象映射到了進(jìn)程地址空間中,實現(xiàn)文件磁盤地址和進(jìn)程虛擬地址空間中一段虛擬地址的一一對映關(guān)系。實現(xiàn)這樣的映射關(guān)系后,進(jìn)程就可以采用指針的方式讀寫操作這一段內(nèi)存,而系統(tǒng)會自動(默認(rèn)并不實時)回寫臟頁面到對應(yīng)的文件磁盤上,即完成了對文件的操作而不必再調(diào)用read,write等系統(tǒng)調(diào)用函數(shù),對文件直接通過內(nèi)存映射讀取從而跨過了頁緩存,減少數(shù)據(jù)拷貝次數(shù),用內(nèi)存讀寫 取代I/O讀寫,提高文件讀取效率。另外,內(nèi)核空間對這段區(qū)域的修改也直接反映用戶空間,從而可以實現(xiàn)不同進(jìn)程間的文件共享,從而達(dá)到進(jìn)程間通信和進(jìn)程間共享的目的。簡言之,很強(qiáng)大。
2.protobuf
? 在數(shù)據(jù)序列化方面微信團(tuán)隊選用了protobuf 協(xié)議,出于通用化的考慮將多樣化的 value 通過 protobuf協(xié)議序列化成統(tǒng)一的內(nèi)存塊(buffer),然后再進(jìn)行相應(yīng)存儲。
2.1 protobuf是什么
protobuf是一種靈活高效的序列化結(jié)構(gòu)機(jī)制,就像xml,但是protobuf更輕量、更快并且更簡單。一旦你限定了你想要的數(shù)據(jù)結(jié)構(gòu),那么你就可以使用特殊的構(gòu)建代碼實現(xiàn)對大量數(shù)據(jù)結(jié)構(gòu)的讀寫,并且支持多種語言哦~你甚至可以更新你的數(shù)據(jù)構(gòu)建,哪怕新的數(shù)據(jù)結(jié)構(gòu)與老的完全相反,這絲毫不影響已經(jīng)部署完成的程序。
也就是說protobuf幫我們輕松實現(xiàn)了序列化和反序列化,即使變更數(shù)據(jù)結(jié)構(gòu),也不會產(chǎn)生太大的影響,這對于數(shù)據(jù)結(jié)構(gòu)多變的實際業(yè)務(wù)場景來說簡直太有必要了。
3.寫入優(yōu)化&空間增長
? 因為標(biāo)準(zhǔn) protobuf并 不提供增量更新的能力,每次寫入都必須全量寫入。 查看代碼我們也能看到最底層調(diào)用的方法是使用的append而非直接替換:
但是這樣就會引發(fā)兩個問題:
1.很大程度上可能存在相同key但是存儲了多個不同的value。? 2.不斷 append 的話,文件大小會增長得不可控。
針對這兩個問題的處理方式是:
1.在程序啟動第一次打開 mmkv 時,不斷用后讀入的 value 替換之前的值,就可以保證數(shù)據(jù)是最新有效的。
2.對于空間增長的問題:以內(nèi)存 pagesize 為單位申請空間,在空間用盡之前都是 append 模式;當(dāng) append 到文件末尾時,進(jìn)行文件重整、key 排重,嘗試序列化保存排重結(jié)果;排重后空間還是不夠用的話,將文件擴(kuò)大一倍,直到空間足夠。所以在每次append之前都會先調(diào)用- (BOOL)ensureMemorySize:(size_t)newSize;方法檢查一下是否有足夠空間,如果沒有則按照每次2倍的大小去擴(kuò)展空間:
3.另外針對空間增長,mmkv還提供了- (void)trim;方法來提供了通過手動調(diào)用減小多余占用內(nèi)存的功能,正如每次擴(kuò)增時按2倍擴(kuò)增,縮減時也是每次除以2:
4.crc 校驗
? 微信團(tuán)隊考慮到文件系統(tǒng)、操作系統(tǒng)都有一定的不穩(wěn)定性,另外增加了 crc 校驗,對無效數(shù)據(jù)進(jìn)行甄別,根據(jù)微信提供的數(shù)據(jù):在 iOS 微信現(xiàn)網(wǎng)環(huán)境上,觀察到有平均約 70w 日次的數(shù)據(jù)校驗不通過。
4.1 crc 校驗簡介
? CRC即循環(huán)冗余校驗碼(Cyclic Redundancy Check):是數(shù)據(jù)通信領(lǐng)域中最常用的一種查錯校驗碼,其特征是信息字段和校驗字段的長度可以任意選定。循環(huán)冗余檢查(CRC)是一種數(shù)據(jù)傳輸檢錯功能,對數(shù)據(jù)進(jìn)行多項式計算,并將得到的結(jié)果附在幀的后面,接收設(shè)備也執(zhí)行類似的算法,以保證數(shù)據(jù)傳輸?shù)恼_性和完整性。也就是接受方和發(fā)送方約定一個用來計算的二進(jìn)制數(shù)(比如x),在整個傳輸過程中,這個數(shù)始終保持不變。循環(huán)冗余校驗碼(CRC)的基本原理是:在K位信息碼后再拼接R位的校驗碼,整個編碼長度為N位,因此,這種編碼也叫(N,K)碼。那么發(fā)送方發(fā)送時根據(jù)約定的x計算出要補(bǔ)全在K位信息碼后的R位校驗碼,然后發(fā)送,接收方接收到數(shù)據(jù)之后通過約定好的x對收到的數(shù)據(jù)進(jìn)行校驗,即可查驗在數(shù)據(jù)傳輸過程中有否出錯。
對比結(jié)果
另外相比較NSUserDefaults還需要手動調(diào)用synchronize保存來說,MMKV為自動保存,無需手動調(diào)用同步。
總結(jié)
以上是生活随笔為你收集整理的MMKV_mmkv之基本介绍的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 为了兴趣爱好,我该选嵌入式么?
- 下一篇: 国外出差见闻之印度