Android數據持久化方案調研-MMKV SP REALM ROOM WCDB...

官方方案對比

SharedPreference

簡稱SP,使用鍵值對的形式保存原始類型的數據,默認以XML格式的文件來存儲這些數據java

  • 適用場景:存儲量小、簡單的數據
  • 優缺點:有本身的內存級的緩存,在數據量小的時候讀取較快,可是跨進程不安全,數據量大的時候加載緩慢,全量寫入,容易引發ANR

SQLite

  • 適用場景:比較複雜數據類型而且較大的數據量,成千上萬的級別
  • 優缺點:相比SP來講,須要在數據量較大的時候纔有優點,數據的獲取較慢,大量寫入須要注意使用事務批處理,性能較高,若是頻繁的單次插入性能不高,直接經過sql操做比較繁瑣,能夠考慮orm框架

File

  • 適用場景:顧名思義比較適用於文件類型的存儲,如圖片或者存儲一些簡單的文本數據或二進制數據
  • 優缺點:最基本的存儲方式,它不對存儲的內容進行任何的格式化處理,全部數據都是原封不動地保存到文件當中的

小結

因爲咱們目前使用的SP方案,咱們的痛點,性能差,和ANR問題,考慮換一種數據存儲方案,首先咱們的數據存儲的場景並非複雜數據類型,量上也不是太大,因此優先考慮的就是MMKV,爲了更清楚的瞭解MMKV的優缺點,因此對比參考下android

開源方案對比

各類方案簡介

名稱 MMKV Realm WCDB Room
方案 mmap nosql SQLCipher SQLite
版本 1.0.24 6.0.2 1.0.8 2.2.3
size 0.15mb 1.5mb 0.7mb 0.05mb
遷移 從SP遷移方便 從SQLite遷移方便
場景 替換SP 替換SQLite 替換SQLite 替換SQLite

注: size 爲armeabi-v7a架構下打包增量大小
mmkv包含lib_c++shared庫的size爲0.3mbc++

性能對比

初始化

初始化 MMKV SP Realm Room WCDB
耗時 30ms 4ms 60ms 15ms 80ms
內存 1mb 約1mb 約2mb 1mb 2mb
cpu峯值 16% 20% 18% 15% 15%

讀寫速度和數據文件大小等數據對比

SP 執行次數 寫入耗時 讀取耗時 數據文件
字符串 200 51ms 4ms 8kb
字符串 1000 171ms 6ms 42kb
Java實體 1000 220ms 87ms 172kb
MMKV 執行次數 寫入耗時 讀取耗時 數據文件
字符串 200 8ms 5ms 4kb
字符串 1000 20ms 9ms 16kb
Java實體 1000 117ms 93ms 128kb
Realm 執行次數 寫入耗時 讀取耗時 數據文件
字符串 200 229ms 74ms 32kb
字符串 1000 606ms 122ms 288kb
Java實體 1000 760ms 130ms 576kb
Room 執行次數 寫入耗時 讀取耗時 數據文件
字符串 200 636ms 160ms 32kb
字符串 1000 1350ms 475ms 48kb
Java實體 1000 1298ms 432ms 68kb
wcdb 執行次數 寫入耗時 讀取耗時 數據文件
字符串 200 636ms 160ms 32kb
字符串 1000 1350ms 475ms 48kb
Java實體 1000 1298ms 432ms 68kb

內存消耗

內存消耗 MMKV SP
初始化 + 查詢1k條 1.7mb 1.2mb
初始化 + 查詢1w條 3.6mb 2.8mb
初始化 + 查詢5w條 10.7mb(文件8mb) 8.5mb(文件8.6mb)

指標備註

字符串數據:含有隨機數的10個字節
運行手機:華爲 Mate10
執行線程:子線程
統計方式:取3次平均值
內存消耗:業務代碼讀取對應數據後釋放本地對象後的內存增量
因爲序列化反序列化會有緩存,Java實體
SP寫入爲apply異步方式
Realm、WCDB、Room 的插入操做均爲單條插入
MMKV、SP 讀取和寫入Java實體對象數據時間包含實體類序列化和反序列化時間,不過因爲序列化反序列化會有緩存,時間會稍偏小git

測試整理

  • 初始化性能,cpu峯值和內存增加都相差無幾,耗時來看,因爲SP和Room都是系統原生的方案,耗時較短。
  • MMKV和SP新增了內存消耗一項,主要是由於本身有一分內存級別的緩存,須要驗證下對內存的影響,從測試數據來看,這兩個方案內存增加至關,能夠接受。
  • MMKV使用protobuf存儲,SP使用xmlprotobuf相比xml來講性能更好,體積也會減少,可是真實存儲空間來看,mmkv的擴容機制(在空間不足時會申請一倍的空間)可能會致使實際使用空間變大,相比較SP的佔用的存儲空間就是真實的數據大小。

開源方案總結

MMKV

MMKV 經過 mmap 內存映射文件,提供一段可供隨時寫入的內存塊,App 只管往裏面寫數據,由操做系統負責將內存回寫到文件,沒必要擔憂 crash 致使數據丟失。而SP則 MMKV 是一個跨平臺的解決方案,寫入性能相比sp有很大提高,適用於須要一個通用的 key-value 存儲組件,有跨進程訪問需求,尤爲是對如今sp存儲方案的不滿的同窗,mmkv同時支持了sp的遷移支持,基本上不用調整太多的代碼,遷移事項下面會詳述。github

Realm

Realm做爲一款移動端的NoSQL框架,官方定位就是替代SQLite等關係型數據庫,跨平臺,性能優秀,有可視化的查看工具。不足也比較明顯,不管是集成包size仍是數據文件都有點大。另外Realm要求當前Bean對象必須直接繼承RealmObject,侵入性很是強。有線程限制,不能跨線程使用數據對象。另外我在寫測試demo的時候發現了一個坑,若是一個線程查詢出列表後,另外一個線程再去增長或刪除會使得本地數據文件產生備份,致使數據庫文件急速增加,達到幾百MB,而且不會自動清理,官方對這個也有說明:sql

WCDB

WCDB是一個高效、完整、易用的移動數據庫框架,基於SQLCipher,支持iOS, macOS和Android數據庫

Room

Room並非一個數據庫,他是在 SQLiteo 的基礎上提供了一個抽象層,讓用戶可以在充分利用 SQLite 的強大功能的同時,獲享更強健的數據庫訪問機制。並保留了靈活的接口適配層。目前WCDB已經支持接入Room:github.com/Tencent/wcd…緩存

ObjectBox

想嘗試的同窗能夠試試 ObjectBox,這個也是GreenDao做者的另外一力做,聽說性能比Realm還要好,因爲本次是對老項目中的SP存儲方案選型替換,暫時先不對比ObjectBox了,後續有時間了完善下相關對比記錄,有幾篇文章你們能夠參考
notes.devlabs.bg/realm-objec…
chejdj.github.io/android/201…安全

綜述

總結下吧,sp 和 mmkv 都是本身有一分內存級別的緩存,因此查詢很是快,可是若是數據量過大,會形成內存溢出,mmkv官方也對這點有說明,不要超過100mb,其實對正常的數據來講,確定到不了這個限制,若是30mb以上的數據,都要考慮使用數據庫類型的存儲了,上面測試數據對於數據庫類型的存儲不太公平,主要針對單次頻繁插入查詢的使用場景,數據庫使用場景通常會多條數據經過事務批量寫入,查詢的時候也會查詢一類數據集合。綜上所述,目前採用mmkv替換sp的實現仍是有很大收益的,性能和跨進程上都有優點,而且避免了sp的ANR問題,體積上也沒有加大多少;若是數據庫方案,建議採用Room,或者在嘗試下上面說的可是沒在本次測試對比的objectbox。感受要注意的挺多,不過零零散散只整理了這麼點...架構

MMKV遷移參考

  • 遷移官方文檔:github.com/Tencent/MMK…

  • MMKV 不支持 Serializable,可是能夠考慮把 Serializable 的 java對象 轉換成 byte 存入MMKV

  • MMKV初始存儲空間4kb,不足的時擴容最少是一倍,而且爲了效率在移除key value不會減少磁盤存儲空間,官方提供了kv.trim方法去縮減磁盤存儲空間,不過官方建議調用時機是有大量移除操做的時候執行,通常無需考慮存儲文件增加問題,但這個時機很差掌握,不過感受能夠按期清理一次

  • SP#getAll SP#registerOnSharedPreferenceChangeListener 等方法不支持,調用會拋出運行時異常,須要注意。getAll由於擦除了類型,因此不支持,感受這是mmkv相對較弱的地方,也爲之後遷移其餘存儲方案增長了成本

  • 一些 Android 設備(API level 19)在安裝/更新 APK 時可能出錯, 致使 libmmkv.so 找不到。而後就會遇到 java.lang.UnsatisfiedLinkError 之類的 crash。有個開源庫 ReLinker 專門解決這個問題,不過如今還在支持19的應用應該很少了

  • 對於歷史項目SP數據可能比較龐大,這樣直接使用官方提供的mmkv#importFromSharedPreferences方法直接對一個文件進行遷移,會形成耗時過長的問題,目前Demo測試數據:測試機型華爲Mate10,一個4MB左右的SP的文件遷移到MMKV大約耗時80ms左右,到了線上應該還會更長,因此爲了不初次使用卡住的體驗問題,這裏提供兩個解決思路:1.在使用前統一遷移,而且給予用戶一個遷移數據的提示;2.在初次使用的時候後臺靜默遷移。目前咱們使用的是第二種思路,這種狀況須要保證數據的準確性,若是有同窗有興趣能夠留言探討

參考

官方和網上各類對比測試文章

相關文章
相關標籤/搜索