MMKV 開源當日即登Github Trending日榜,三往後榮登周榜。MMKV 在騰訊內部開源半年,獲得公司內部團隊的普遍應用和一致好評。git
MMKV 是基於 mmap 內存映射的移動端通用 key-value 組件,底層序列化/反序列化使用 protobuf 實現,性能高,穩定性強。從 2015 年中至今,在 iOS 微信上使用已有近 3 年,其性能和穩定性通過了時間的驗證。近期已移植到 Android 平臺,移動端全平臺通用,並所有在 Github 上開源。MMKV源起 在微信客戶端的平常運營中,時不時就會爆發特殊文字引發系統的 crash,參考文章:《iOS微信特殊字符保護方案》,文章裏面設計的技術方案是在關鍵代碼先後進行計數器的加減,經過檢查計數器的異常,來發現引發閃退的異常文字。在會話列表、會話界面等有大量 cell 的地方,但願新加的計時器不會影響滑動性能;另外這些計數器還要永久存儲下來——由於閃退隨時可能發生。這就須要一個性能很是高的通用 key-value 存儲組件,咱們考察了 SharedPreferences、NSUserDefaults、SQLite 等常見組件,發現都沒能知足如此苛刻的性能要求。考慮到這個防 crash 方案最主要的訴求仍是實時寫入,而 mmap 內存映射文件恰好知足這種需求,咱們嘗試經過它來實現一套 key-value 組件。github
MMKV原理 • 內存準備 經過 mmap 內存映射文件,提供一段可供隨時寫入的內存塊,App 只管往裏面寫數據,由操做系統負責將內存回寫到文件,沒必要擔憂 crash 致使數據丟失。數據組織 數據序列化方面咱們選用 protobuf 協議,pb 在性能和空間佔用上都有不錯的表現。 • 寫入優化 考慮到主要使用場景是頻繁地進行寫入更新,咱們須要有增量更新的能力。咱們考慮將增量 kv 對象序列化後,append 到內存末尾。 • 空間增加 使用 append 實現增量更新帶來了一個新的問題,就是不斷 append 的話,文件大小會增加得不可控。咱們須要在性能和空間上作個折中。算法
更詳細的設計原理參考 GitHub Wiki 文檔。微信
MMKV功能 MMKV 優勢 • 高效
MMKV 使用 mmap 來保證內存與文件的同步, 底層使用 protobuf 來存儲數據, 深刻挖掘了操做系統的潛力來達到最高的性能。 • 易用
你能夠像使用 Dictionary 同樣來使用 MMKV, 無需任何配置。全部變動立刻生效, 無需調用任何 sync 之類的同步接口。 • 小巧
o 只有十幾個文件: MMKV 包含了序列化/反序列化幫助類和 mmap 邏輯,再無其餘累贅邏輯。代碼很是精簡。 o 二進制少於 60K: MMKV 每一個架構只加了不到 60K 的二進制大小(解壓後)。通常 App 都會壓縮打包發佈,實際上上會比 60K 更小。 MMKV for Android 特有功能 咱們在遷移到 Android 的過程當中,不是簡簡單單地照搬 iOS 的實現,深刻分析了 Android 平臺現有 kv 組件的痛點,在原有功能基礎上,開發了 Android 特有的功能。markdown
• 多進程訪問
經過與 Android 開發同窗的溝通,瞭解到系統自帶的 SharedPreferences 對多進程的支持很差。現有基於 ContentProvider 封裝的實現,雖然多進程是支持了,可是性能低下,常常致使 ANR。考慮到 mmap 共享內存本質上的多進程共享的,咱們在這個基礎上,深刻挖掘了 Android 系統的能力,提供了多是業界最高效的多進程數據共享組件。具體實現原理能夠前往 GitHub 查看源碼和 wiki 文檔。架構
• 匿名內存
在多進程共享的基礎上,考慮到某些敏感數據(例如密碼)須要進程間共享,可是不方便落地存儲到文件上,直接用 mmap 不合適。咱們瞭解到 Android 系統提供了 Ashmem 匿名共享內存的能力,發現它在進程退出後就會消失,不會落地到文件上,很是適合這個場景。咱們很愉快地提供了 Ashmem MMKV 的功能。app
• 數據加密
不像 iOS 全部設備都提供了硬件層級的加密機制,在 Android 環境裏,數據加密是很是必須的。MMKV 使用了 AES CFB-128 算法來加密/解密。咱們選擇 CFB 而不是常見的 CBC 算法,主要是由於 MMKV 使用 append-only 實現插入/更新操做,流式加密算法更加合適。事實上這個功能也回饋到了 iOS 版,因此如今兩個系統的 MMKV 都有加密功能。ide
MMKV性能 iOS 性能對比 咱們將 MMKV 和 NSUserDefaults 進行對比,重複讀寫操做 1w 次。相關測試代碼在 iOS/MMKVDemo/MMKVDemo/,結果見以下圖表。oop
可見,MMKV 在寫入性能上遠遠超越 NSUserDefaults,在讀取性能上也有相近或超越的表現。性能
(測試機器是 iPhone X 256 G,iOS 12 beta 2,每組操做重複 1w 次,時間單位是 ms。)Android 性能對比 咱們將 MMKV 和 SharedPreferences、SQLite 進行對比, 重複讀寫操做 1k 次。相關測試代碼在 Android/MMKV/mmkvdemo/。結果以下圖表。
• 單進程性能
可見,MMKV 在寫入性能上遠遠超越 SharedPreferences & SQLite,在讀取性能上也有相近或超越的表現。
• 多進程性能
可見,MMKV 不管是在寫入性能仍是在讀取性能,都遠遠超越 MultiProcessSharedPreferences & SQLite & SQLite, MMKV 在 Android 多進程 key-value 存儲組件上是不二之選。
Github 開源地址: github.com/tencent/mmk… 歡迎 Star、提 Issue 和 PR!