MMKV简介

MMKV是腾讯基于mmap内存映射开发的通用key-value组件,底层使用protobuf实现序列化\反序列化功能,性能高,稳定性强。并且已在GitHub上开源,地址如下

https://github.com/Tencent/MMKV

MMKV的原理如下

  • 内存准备
    通过mmap内存映射文件,提供一段可供随时写入的内存块,App只管往里面写数据,由操作系统负责将内存回写到文件,不必担心Crash导致数据丢失。
  • 数据组织
    数据序列化方面,MMKV使用protobuf协议,protobuf在性能和空间上都有不错的表现。
  • 写入优化
    标准protobuf不提供增量更新的能力,每次写入都必须全量写入。但MMKV提供了增量更新的能力:将增量KV对象序列化后,直接append到内存末尾,这样同一个key就会有新旧两份数据,最新的数据在最后。
  • 空间增长
    使用append来实现增量更新会带来一个新的问题,就是不断append的话,文件大小会增长得不可控,例如通过key不断更新的话,是可能会耗尽几百M甚至上G的空间,而事实上KV文件就这一个key,不到1K的空间就存的下。所以MMKV在性能和空间上做了一个折中:以内存pagesize为单位申请内存,在空间用尽之前都是append模式;当append到文件末尾时,进行文件整理、key去重,尝试序列化保存去重后的结果,去重后空间还是不够用的话,将文件扩大一倍,直到空间足够。

在Android中使用MMKV

首先在模块的build.gradle中引入依赖

dependencies {
    implementation 'com.tencent:mmkv:1.2.13'
}

在使用前需要进行初始化

val result = MMKV.initialize(this)
log(result)

这里会返回MMKV默认的文件存储地址,如下

/data/user/0/com.cmri.mmkv/files/mmkv

使用时也非常简单

kv.putInt("a", 1) //写入
val readResult = kv.getInt("a",0) //读
log(readResult.toString())

MMKV支持Java基本数据类型,如Boolean\Int\String\Float\Long\Byte Array\String Set等操作

MMKV与SharedPreferences性能对比

官网上对MMKV与SP的性能对比如下

手机 kvm 手机kvm软件_android

我们对此还是持怀疑态度,亲自写代码来测试下。

测试手机,华为NOVA 6,鸿蒙系统,小米6 android9.0
测试代码示例如下

private fun testMMKVWrite() {
    val begin = System.currentTimeMillis()
    for (i in 0 until 1000) {
        MMKV.defaultMMKV().putInt(i.toString(), i)
    }
    val end = System.currentTimeMillis()
    log("testMMKVWrite:" + (end - begin))
}

private fun testSPWrite() {
    val begin = System.currentTimeMillis()
    for (i in 0 until 1000) {
        mSp.edit().putInt(i.toString(), i).commit()
    }
    val end = System.currentTimeMillis()
    log("testSPWrite:" + (end - begin))
}
private fun testMMKVRead() {
     val begin = System.currentTimeMillis()
     for (i in 0 until 1000) {
         MMKV.defaultMMKV().getInt(i.toString(), 0)
     }
     val end = System.currentTimeMillis()
     log("testMMKVRead:" + (end - begin))
 }

 private fun testSPRead(){
     val begin = System.currentTimeMillis()
     for (i in 0 until 1000) {
         mSp.getInt(i.toString(), 0)
     }
     val end = System.currentTimeMillis()
     log("testSPRead:" + (end - begin))
 }

测试出来的对比数据如下

写场景

  • MMKV 鸿蒙:5ms,小米6:18ms
  • SP 鸿蒙:41ms,小米6 :118ms

读场景

  • MMKV 4ms 小米6:12ms
  • SP 29ms 小米6:90ms

先写后读场景

  • MMKV 3ms 小米6:3ms
  • SP 1ms 小米6:3ms

以上综合比较下来,MMKV的读写性能确实比SP要好。尤其在写性能上要好很多。