本文转自微信开发团队凌国的分享。原文

MMKV 是基于 mmap 内存映射的移动端通用 key-value 组件,底层序列化/反序列化使用 protobuf 实现,性能高,稳定性强。从 2015 年中至今,在 iOS 微信上使用已有近 3 年,其性能和稳定性经过了时间的验证。近期已移植到 Android 平台。在腾讯内部开源半年之后,得到公司内部团队的广泛应用和一致好评。现在一并对外开源:

https://github.com/tencent/mmkv

欢迎 Star、提 Issue 和 PR。

MMKV 源起

在微信客户端的日常运营中,时不时就会爆发特殊文字引起系统的 crash,参考文章,文章里面设计的技术方案是在关键代码前后进行计数器的加减,通过检查计数器的异常,来发现引起闪退的异常文字。在会话列表、会话界面等有大量 cell 的地方,希望新加的计时器不会影响滑动性能;另外这些计数器还要永久存储下来——因为闪退随时可能发生。这就需要一个性能非常高的通用 key-value 存储组件,我们考察了 SharedPreferences、NSUserDefaults、SQLite 等常见组件,发现都没能满足如此苛刻的性能要求。考虑到这个防 crash 方案最主要的诉求还是实时写入,而 mmap 内存映射文件刚好满足这种需求,我们尝试通过它来实现一套 key-value 组件。

MMKV 原理

  • 内存准备
    通过 mmap 内存映射文件,提供一段可供随时写入的内存块,App 只管往里面写数据,由操作系统负责将内存回写到文件,不必担心 crash 导致数据丢失。

  • 数据组织
    数据序列化方面我们选用 protobuf 协议,pb 在性能和空间占用上都有不错的表现。

  • 写入优化
    考虑到主要使用场景是频繁地进行写入更新,我们需要有增量更新的能力。我们考虑将增量 kv 对象序列化后,append 到内存末尾。

  • 空间增长
    使用 append 实现增量更新带来了一个新的问题,就是不断 append 的话,文件大小会增长得不可控。我们需要在性能和空间上做个折中。

更详细的设计原理参考前文 《MMKV——iOS 下基于 mmap 的高性能通用 key-value 组件》。

MMKV for Android 特有功能

我们不是简简单单地照搬 iOS 的实现,在迁移到 Android 的过程中,深入分析了 Android 平台现有 kv 组件的痛点,在原有功能基础上,开发了 Android 特有的功能。

  • 多进程访问
    通过与 Android 开发同学的沟通,了解到系统自带的 SharedPreferences 对多进程的支持不好。现有基于 ContentProvider 封装的实现,虽然多进程是支持了,但是性能低下,经常导致 ANR。考虑到 mmap 共享内存本质上的多进程共享的,我们在这个基础上,深入挖掘了 Android 系统的能力,提供了可能是业界最高效的多进程数据共享组件。具体实现原理我们中秋节后分享,心急的同学可以前往 GitHub 查看源码和 wiki 文档。

  • 匿名内存
    在多进程共享的基础上,考虑到某些敏感数据(例如密码)需要进程间共享,但是不方便落地存储到文件上,直接用 mmap 不合适。我们了解到 Android 系统提供了 Ashmem 匿名共享内存的能力,发现它在进程退出后就会消失,不会落地到文件上,非常适合这个场景。我们很愉快地提供了 Ashmem MMKV 的功能。

  • 数据加密
    不像 iOS 提供了硬件层级的加密机制,在 Android 环境里,数据加密是非常必须的。MMKV 使用了 AES CFB-128 算法来加密/解密。我们选择 CFB 而不是常见的 CBC 算法,主要是因为 MMKV 使用 append-only 实现插入/更新操作,流式加密算法更加合适。事实上这个功能也回馈到了 iOS 版,所以现在两个系统的 MMKV 都有加密功能。

MMKV 使用

iOS 的使用在前文已经陈述,这里简单介绍一下 Android 的用法。

Android 快速上手

MMKV 已托管到 bintray(JCenter),可以直接使用。在 App 的 build.gradle 里加上依赖:

MMKV 的使用非常简单,所有变更立马生效,无需调用 syncapply。 在 App 启动时初始化 MMKV,设定 MMKV 的根目录(files/mmkv/),例如在 MainActivity 里:

MMKV 提供一个全局的实例,可以直接使用:

如果不同业务需要区别存储,也可以单独创建自己的实例:

SharedPreferences 迁移

  • MMKV 提供了 importFromSharedPreferences() 函数,可以比较方便地迁移数据过来。

  • MMKV 还额外实现了一遍 SharedPreferences、SharedPreferences.Editor 这两个 interface,在迁移的时候只需两三行代码即可,其他 CRUD 操作代码都不用改。

更详细的用法可以参看 GitHub 上的 wiki 文档。

MMKV 性能

iOS 性能对比

我们将 MMKV 和 NSUserDefaults 进行对比,重复读写操作 1w 次。相关测试代码在 iOS/MMKVDemo/MMKVDemo/,结果见如下图表。

image

(测试机器是 iPhone X 256 G,iOS 12 beta 2,每组操作重复 1w 次,时间单位是 ms。)

可见,MMKV 在写入性能上远远超越 NSUserDefaults,在读取性能上也有相近或超越的表现。

Android 性能对比

我们将 MMKV 和 SharedPreferences、SQLite 进行对比, 重复读写操作 1k 次。相关测试代码在 Android/MMKV/mmkvdemo/。结果如下图表。

  • 单进程性能
    可见,MMKV 在写入性能上远远超越 SharedPreferences & SQLite,在读取性能上也有相近或超越的表现。

    image

    (测试机器是 Pixel 2 XL 64G,Android 8.1,每组操作重复 1k 次,时间单位是 ms。)

  • 多进程性能
    可见,MMKV 无论是在写入性能还是在读取性能,都远远超越 MultiProcessSharedPreferences & SQLite & SQLite, MMKV 在 Android 多进程 key-value 存储组件上是不二之选

    image

    (测试机器是 Pixel 2 XL 64G,Android 8.1,每组操作重复 1k 次,时间单位是 ms。)

点击原文直接访问 GitHub 源码。

Android MMKV相关推荐

  1. android mmkv使用_MMKV解读

    一.首先看一下介绍(mmkv官方介绍) MMKV--基于 mmap 的高性能通用 key-value 组件 MMKV 是基于 mmap 内存映射的 key-value 组件,底层序列化/反序列化使用 ...

  2. Android MMKV使用及 MMAP原理

    什么是MMKV MMKV--基于 mmap 的高性能通用 key-value 组件,底层序列化/反序列化使用 protobuf 实现,性能高,稳定性强. MMKV 是基于 mmap 内存映射的移动端通 ...

  3. MMKV_荣登Github日榜!微信最新开源MMKV

    MMKV 开源当日即登Github Trending日榜,三日后荣登周榜.MMKV 在腾讯内部开源半年,得到公司内部团队的广泛应用和一致好评. MMKV 是基于 mmap 内存映射的移动端通用 key ...

  4. 智能硬件蓝牙配网方案概要

    智能硬件开发系列 Google Protobuf 实践使用开发 智能硬件蓝牙配网方案概要 JNI开发必学C++基础 JNI开发必学C++使用实践 Android Studio 4.0.+NDK项目开发 ...

  5. Google Protobuf 实践使用开发

    Android 敏捷开发助手 Lottie动画 轻松使用 PNG.JPG等普通图片高保真转SVG图 Android 完美的蒙层方案 Android MMKV框架引入使用 强大无匹的自定义下拉列表 Go ...

  6. 开源|携程机票 App KMM 跨端 KV 存储库 MMKV-Kotlin

    作者简介 禹昂,携程移动端资深工程师,专注于 Kotlin 移动端跨平台领域,Kotlin 中文社区核心成员,图书<Kotlin 编程实践>译者. 一.背景 携程机票移动端研发团队自 20 ...

  7. Android 三方库lottie、mmkv的使用

    lottie lottie是Airbnb开源的一个面向 iOS.Android.React Native 的动画库,能实现精美.复杂的动画效果. Android端使用方法 首先,需要在当前项目的bui ...

  8. 神器Android键值数据库MMKV——基于 mmap 的高性能通用 key-value 组件

    MMKV 是基于 mmap 内存映射的 key-value 组件,底层序列化/反序列化使用 protobuf 实现,性能高,稳定性强.从 2015 年中至今在微信上使用,其性能和稳定性经过了时间的验证 ...

  9. 【Android源码面试宝典】MMKV从使用到原理分析(一)

    去年,我们写过一篇文章,对于android原生提供的key-value存储API SharePreference,进行了从使用到原理的深入分析,同时对其中存在的ANR问题.存取慢等问题,进行了深入的探 ...

最新文章

  1. 基于mpi的奇偶排序_并行程序设计(第2版)pdf
  2. Linux运维需要知道的Redis经验
  3. Veronica博士的研究方向的介绍
  4. win7 64系统无法看见其他计算机,win7一直显示正在启动进不了系统怎么办
  5. C#入门详解(12)
  6. 用Semisynchronous Replication半同步,mk-table-checksum数据同步一致性检查,监控主从同步运行状态的脚本等方式加强SQL性能和数据审核...
  7. VS2008中VC 项目 文件目录的管理 (最终无错误版)
  8. Mac 终端 显示隐藏文件
  9. docker 安装 MySQL 8,并减少内存占用 记录
  10. 基于WEB的PDF打印——浏览器中静默打印PDF文件
  11. Android自定义View 顶部导航栏
  12. Windows安全更新出现0x800f081f错误解决方案
  13. 工程师的浪漫:用机械臂画一个爱心
  14. Xilinx SDx 2018.3安装
  15. java零到一:Servlet和JSP-7:转发、重定向的区别 和状态管理
  16. 狼人杀超详入门攻略3之各角色玩法
  17. Java + OpenCV 模板匹配
  18. 关于2020西门子杯工业自动化线上赛总结(初赛过控篇)
  19. SIMCOM 7600、7670的MQTT连接流程(上)--连接、关闭及订阅
  20. 帕雷托法则(常说的二八法则)

热门文章

  1. 支付--支付宝手机网站支付(WAP)
  2. 如何在网页中设置一个定时器计算时间?
  3. java转go之初体验(一)
  4. c语言 long与integer,VB中Integer(整型)和Long(长整型)有什么区别?
  5. SP服务商Java短信平台的软件模型和实现(吴宏杰,赵雷,杨季文,苏州大学计算机科学和技术学院)...
  6. Linux命令之vmstat命令
  7. python简单代码运用到桌面壁纸_五行Python代码自动换你的电脑桌面壁纸(内附源码和exe)...
  8. ZooKeeper3.7.0 编译客户端zookeeper-client
  9. 在linux上下载使用cisco anyconnect Software
  10. Flask、sqlite3、pipenv实现用户注册和登录(HandBook,菜鸟都会的)