MMKV——2.原理

1.MMKV——1.使用
2.MMKV——2.原理

1. mmap高性能存取的基石

MMKV通過mmap 內存映射文件來進行讀寫操作的,這是其效率高于普通IO的原因。

普通IO

傳統(tǒng)的read首先將文件內容從硬盤拷貝到內核空間的一個緩沖區(qū),然后再將這些數據拷貝到用戶空間,這個過程中,實際上完成了\color{red}{兩次數據拷貝}。

內存映射

mmap將文件直接映射到用戶空間,所以中斷處理函數根據這個映射關系,直接將文件從硬盤拷貝到用戶空間,只進行了 \color{red}{一次數據拷貝},因此,mmap內存映射的效率要比read/write效率高。

為什么不直接用內存映射代替IO?

既然MMKV使用的內存映射優(yōu)于IO,為什么還要使用IO?

首先要明白,直接將文件映射到虛擬內存,意味著沒有數據沒有緩存在內核緩存空間,而是直接讀到了用戶空間,而系統(tǒng)的IO和內核緩存搭配可以使得部分的文件使用效率更高。(OS會根據局部性原理在一次read()系統(tǒng)調用的時候預讀取更多的文件數據到內核空間緩沖區(qū)中,這樣當下一次read()系統(tǒng)調用的時候發(fā)現要讀取的數據已經存在于內核空間緩沖區(qū)中的時候只要直接拷貝數據到用戶空間緩沖區(qū)中即可,無需再進行一次低效的磁盤I/O操作,且磁盤的大小要遠遠超過內存)

而且mmap映射的文件是大于一個內存頁大小的(\color{red}{4k}),并且是\color{red}{4k的倍數}。

也就是說兩個方式都是有優(yōu)缺點的,所以不存在代替這個說法,只能通過分析其場景而選擇不同的方式。

參考:
mmap 文件映射內存詳解
高性能IO 之 內存映射 mmap的理解

2.采用Protobuf協議存儲key-value結構

Protobuf協議

protobuf 是google開源的一個序列化框架,類似xml,json,最大的特點是基于二進制,比SharedPreferences使用的傳統(tǒng)的XML表示同樣一段內容要短小得多。同樣這也不能說明Protobuf優(yōu)于XML,關于Protobuf的更多內容如下:

Protobuf協議格式詳解
深入 ProtoBuf - 簡介

寫入優(yōu)化

標準 protobuf 和SharedPreferences 一樣,每次寫入kv對象都必須全量寫入。也就是寫入之前將所有數據加載到內存中,然后判斷新增的key是否已經存在,完成更新或增加后在全部寫入文件。

MMKV中采用增量更新的方式處理protobuf,當需要寫入kv對象時,不論是新增還是更新都將其直接加入文件的末尾,這樣大大增加了寫入效率。

上面的做法必然帶來兩個問題
1.必然導致同一key值會有新舊若干份數據,最新的數據在最后。
2.文件大小會增長得不可控。同一個 key 不斷更新的話,是可能耗盡幾百 M 甚至上 G 空間。

針對第一個問題,在讀取時,針對同一個 key使用后讀入的 value 替換之前的值,就可以保證數據是最新有效的。

針對第二個問題,有上文可知MMKV的文件必然是稍大于\color{red}{4k}(一個內存頁的大小)的倍數,當寫入的數據小于4k時,可以繼續(xù)寫入,因為本身文件大小就已經略大于4k了,有點很小的浪費,當寫入數據超過4k的倍數后,進行文件重整、key 排重,嘗試序列化保存排重結果;排重后空間還是不夠用的話,將文件在增加4k,直到空間足夠。

3.通過crc 校驗確保數據有效性

文件系統(tǒng)、操作系統(tǒng)都有一定的不穩(wěn)定性,MMKV使用crc 校驗確保數據有效性,關于crc 校驗,可以參考:

CRC校驗原理及代碼

4.多進程設計與實現

這一步官方有詳盡的說明,如下:
多進程設計與實現

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容