當前位置:編程學習大全網 - 源碼下載 - 12騰訊MMKV的原理與實現

12騰訊MMKV的原理與實現

SharedPreferences是Google提供的壹種輕量級存儲方案,使用方便,不需要啟動新的線程就可以直接存儲數據。

然而,它也帶來了許多問題,尤其是由SP引起的ANR問題,這是非常普遍的。

正因為如此,後來出現了壹些SP的替代方案,比如MMKV。

本文主要包括以下內容。

1中的問題。共享首選項

2.2的基本使用和介紹。MMKV

3.3的原則。MMKV

1.讀寫模式:直接I/O。

2.數據格式:xml

3.寫入模式:完全更新

因為SP使用xml格式保存數據,所以每次只能將更新的數據全部替換。

這意味著,如果我們有100條數據,如果只更新壹條數據,我們還需要將所有數據轉換成xml格式,然後通過io寫入文件。

這也導致SP寫效率低。

如上所示

1.commit有壹個返回值,指示修改是否提交成功。

2 .提交是同步的,在磁盤操作成功之前不會完成。

因此,當數據量相對較大時,使用commit很可能會導致ANR。

提交是同步的,SP也提供異步應用。

Apply是將修改後的數據原子提交到內存,然後異步提交到硬件磁盤,而commit是同步提交到硬件磁盤。因此,當提交多個並發提交時,它們將在操作之前等待已處理的提交保存到磁盤,從而降低效率。Apply只是原子性的提交給內容,後面調用apply的函數會直接覆蓋之前的內存數據,壹定程度上提高了不少效率。

但是申請也會引起ANR問題。

為了保證異步任務能夠及時完成,在生命周期處於handleStopService()、handlePauseActivity()和handleStopActivity()時會調用QueuedWork.waitToFinish(),等待寫任務完成。

所以當數據量比較大的時候,apply也會造成ANR。

不僅是寫操作,所有的getXXX()方法都是同步的。當主線程調用get方法時,它必須等待SP完成加載,這也可能導致ANR。

調用getSharedPreferences()方法最終會調用SharedPreferenceSimpl # startloadFromdisk()方法來啟動線程異步讀取數據。

如您所見,啟動壹個線程來異步讀取數據。當我們在讀取壹個比較大的數據,還沒有讀完,然後調用getXXX()方法。

當在同步方法中調用wait()方法時,它將等待getSharedPreferences()方法啟動的線程完成讀取數據,然後再繼續。如果讀取幾KB的數據還可以,假設讀取壹個大文件,必然會造成主線程阻塞。

MMKV是基於mmap內存映射的鍵值組件,底層序列化/反序列化由protobuf實現,性能高,穩定性強。從2015年中開始在微信上使用,性能和穩定性得到了時間的驗證。最近還移植到了Android/macOS/Win32/POSIX平臺,而且是開源的。

1.MMKV實現了SharedPreferences接口,可以無縫切換。

2.通過mmap內存映射文件提供壹個可以隨時寫入的內存塊。App只往裏面寫數據,操作系統負責把內存寫回文件,不用擔心崩潰導致數據丟失。

3.為3選擇protobuf協議。MMKV數據序列化,pb在性能和空間占用方面都有不錯的表現。

4.SP是全更新,MMKV是增量更新,有性能優勢。

詳細的使用細節可以在文件中找到:github.com/Tencent/MMK…

我們知道SP是基於IO來寫和操作的。為了理解IO,我們需要先理解用戶空間和內核空間。

文件寫入過程:

1.調用write來告訴內核要寫入的數據的起始地址和長度。

2.內核將數據復制到內核緩存中。

3.它由操作系統調用,將數據復制到磁盤並完成寫入。

Linux通過將虛擬內存區域與磁盤上的對象相關聯來初始化虛擬內存區域的內容。這個過程稱為內存映射。

Mmap將在進程的虛擬內存中分配地址空間,並創建映射關系。

實現這種映射關系後,就可以通過指針讀寫這段內存,系統會自動寫回對應的文件盤。

可以看出,MMAP的寫入速度與內存基本相同,遠高於SP,這也是MMKV更快的原因。

但是,這也會導致SP根據需要完全更新數據。

MMKV數據結構如下

MMKV使用Protobuf存儲數據,節省冗余數據更少,節省空間更大,並且可以方便地在末尾添加數據。

增量寫入

不管關鍵字是否重復,數據都直接追加到前面的數據中。這樣效率更高,更新數據只需要插入壹段數據。

當然,這也會帶來問題。內容增量添加,文件越來越大怎麽辦?

當文件大小不夠時,需要寫全。從數據中去掉重復鍵後,如果文件大小滿足寫入數據的大小,可以直接更新滿寫量,否則需要擴容。(擴展時,根據每個K-V的平均大小來計算未來可能需要的文件大小進行擴展,防止定期滿量程寫入。)

  • 上一篇:如何編寫高質量的VB代碼
  • 下一篇:在windows中安裝了redis,為什麽找不到這個服務
  • copyright 2024編程學習大全網