MMKV:轻巧高效的跨平台键值存储解决方案

MMKV:轻巧高效的跨平台键值存储解决方案

引言

在移动应用的开发中,数据存储是一个至关重要的环节。随着移动应用的普及和功能的增多,应用需要存储和管理各种类型的数据,包括用户配置信息、缓存数据、临时状态等。传统的数据存储方式如SharedPreferences在一些场景下存在性能瓶颈和局限性,因此我们需要寻找一种更轻量、高效的解决方案。

传统的数据存储方式,如SharedPreferences,虽然简单易用,但在某些情况下存在一些不足之处。首先,SharedPreferences存储的数据会被序列化成XML格式,导致存储和读取的速度相对较慢。其次,SharedPreferences是单线程操作的,如果在多个线程同时写入或读取数据,就容易出现数据安全和一致性问题。此外,SharedPreferences的内存占用也相对较高,特别是在存储大量数据时。

为了解决这些问题,我们需要寻找一种更轻量、高效的数据存储解决方案。而MMKV(Meituan Mapped Key-Value)就是一款非常优秀的跨平台键值存储库,由微信团队开发并开源。MMKV具有轻巧高效、跨平台支持的特点,是替代SharedPreferences的理想选择。

接下来,我们将介绍MMKV的优势,以及在移动应用开发中的实际应用场景。我们还会提供MMKV的使用指南,并进行性能测试,验证其高性能特点。最后,我们会总结MMKV的优势和适用场景,鼓励开发者尝试并采用MMKV,以提升应用的数据存储效率和性能表现。

MMKV简介

MMKV 是一个基于 mmap 内存映射的 key-value 组件,底层序列化/反序列化使用 protobuf 实现,性能高,稳定性强。自 2015 年中至今,在微信上得到广泛应用,其性能和稳定性经过了时间的验证。最近,MMKV 已成功移植到 Android / macOS / Win32 / POSIX 平台并且已经开源。

MMKV源起

在微信客户端的日常运营中,时不时就会因特殊文字引起系统 crash。为了解决这个问题,我们需要在关键代码前后进行计数器的加减,通过检查计数器的异常来发现引起闪退的异常文字。但是在一些包含大量 cell 的页面,如会话列表和会话界面,新增的计数器会影响滑动性能,并且这些计数器需要被永久保存以防止意外崩溃。为了满足这些需求,我们需要一个高性能的通用 key-value 存储组件。考虑到防崩溃方案的主要需求是实时写入,而 mmap 内存映射文件正好符合这一要求,我们决定尝试利用它来开发一个 key-value 组件,即 MMKV。

MMKV原理

  • 内存准备:通过 mmap 内存映射文件,为 App 提供一个可随时写入的内存块,App 只需将数据写入其中,而操作系统负责将内存内容写回文件,避免了因崩溃导致数据丢失的风险。
  • 数据组织:为了实现数据序列化,我们采用了 protobuf 协议,该协议在性能和空间利用方面表现优异。
  • 写入优化:考虑到写入更新频繁是主要使用场景,我们需要支持增量更新。因此,我们选择将增量 kv 对象序列化后,追加到内存末尾。
  • 空间管理:使用追加方式实现增量更新可能会导致文件大小无法控制地增长。为了在性能和空间利用之间取得平衡,我们需要做进一步的优化。

MMKV特点

  1. 轻巧高效:MMKV采用内存映射技术,将数据直接映射到内存中,避免了数据的序列化和反序列化过程,从而提高了读写速度。
  2. 跨平台支持:MMKV不仅支持在Android平台上使用,还提供了iOS、Windows等多个平台的支持,使开发者可以在不同平台上统一使用MMKV进行数据存储。
  3. 性能优越:相较于传统的SharedPreferences,MMKV具有更好的性能表现,尤其在大量数据读写和多线程操作时表现更为出色。

与SharedPreferences相比,MMKV在性能和功能上有明显优势。SharedPreferences的数据存储采用XML格式,而MMKV直接将数据映射到内存中,避免了XML解析过程,因此读写速度更快。此外,MMKV支持多线程读写操作,不会出现数据安全问题,而SharedPreferences在多线程操作时需要考虑同步和锁机制。

示例代码(对比使用SharedPreferences和MMKV进行数据存储的示例):

// 使用SharedPreferences存储数据
SharedPreferences sharedPreferences = context.getSharedPreferences("MyPrefs", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("key", "value");
editor.apply();// 使用MMKV存储数据
MMKV mmkv = MMKV.defaultMMKV();
mmkv.encode("key", "value");// 从SharedPreferences读取数据
String valueFromPrefs = sharedPreferences.getString("key", "");// 从MMKV读取数据
String valueFromMMKV = mmkv.decodeString("key");

通过以上示例代码的对比,可以清楚地看出MMKV相对于SharedPreferences的优势,包括更高的性能和更便捷的多线程支持。因此,MMKV是一款在移动应用开发中非常值得推荐和使用的数据存储库。

MMKV的优势

相较于SharedPreferences,MMKV具有以下优势:

  1. 性能更好:MMKV采用内存映射技术,将数据直接映射到内存中,避免了数据的序列化和反序列化过程,从而提高了读写速度。在大量数据读写和多线程操作时表现更为出色。
  2. 支持多线程读写:MMKV的底层使用了锁机制,支持多线程并发读写操作,不会出现数据安全问题。而SharedPreferences在多线程操作时需要考虑同步和锁机制。
  3. 内存占用更低:MMKV使用内存映射技术,不会像SharedPreferences那样将数据全部读入内存,因此内存占用更低,特别是在存储大量数据时表现更为明显。

MMKV实际应用场景

MMKV适用于移动应用开发中的各种场景,如替代SharedPreferences存储用户配置信息、缓存数据等。下面介绍一些常见的应用场景:

  1. 存储用户配置信息:移动应用通常需要保存用户的一些配置信息,如语言、主题、字体大小等。使用MMKV可以方便地将这些配置信息存储在本地,同时具有更高的读写速度和更低的内存占用。
  2. 缓存数据:移动应用中的一些常用数据,如网络请求数据、图片等,可以使用MMKV进行本地缓存。MMKV具有更高的读写速度和更低的内存占用,可以提升用户体验和应用性能。
  3. 状态保存:在某些场景下,应用需要保存一些临时状态,如用户登录状态、应用退出前的数据保存等。使用MMKV可以轻松地将这些状态存储在本地,并支持多线程并发读写操作,避免出现数据安全问题。

总之,MMKV在移动应用开发中具有广泛的应用场景,特别是在大量数据读写和多线程操作时表现更为出色。因此,我们鼓励开发者尝试并采用MMKV,以提升应用的数据存储效率和性能表现。

使用指南

5.1 Android平台上集成和使用MMKV

  1. 在项目的build.gradle文件中添加依赖:

    dependencies {implementation 'com.tencent:mmkv-static:1.2.7'
    }
    
  2. 在Application的onCreate方法中进行初始化:

    MMKV.initialize(this);
    
  3. 使用MMKV进行数据存储和读取:

    // 获取默认的MMKV对象
    MMKV mmkv = MMKV.defaultMMKV();// 存储数据
    mmkv.encode("key", "value");// 读取数据
    String value = mmkv.decodeString("key", "");
    

5.2 iOS平台上集成和使用MMKV

  1. 使用Cocoapods添加依赖:

    pod 'MMKV', '~> 1.2.7'
    
  2. 在AppDelegate.m文件中进行初始化:

    #import "MMKV.h"- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {[MMKV initialize];return YES;
    }
    
  3. 使用MMKV进行数据存储和读取:

    // 获取默认的MMKV对象
    MMKV *mmkv = [MMKV defaultMMKV];// 存储数据
    [mmkv setString:@"value" forKey:@"key"];// 读取数据
    NSString *value = [mmkv getStringForKey:@"key" defaultValue:@""];
    

5.3 示例代码

以下是一个简单的示例,展示如何在Android平台上使用MMKV进行数据存储和读取:

public class MainActivity extends AppCompatActivity {private MMKV mmkv;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 获取默认的MMKV对象mmkv = MMKV.defaultMMKV();// 存储数据mmkv.encode("key", "value");// 读取数据String value = mmkv.decodeString("key", "");Toast.makeText(this, "读取到的数据:" + value, Toast.LENGTH_SHORT).show();}
}

以上代码中,我们在Activity的onCreate方法中初始化了MMKV,并使用encode方法存储了一条数据,然后使用decodeString方法读取该数据。

性能测试

为了验证MMKV的高性能特点,我们可以进行一些简单的性能测试,并与其他数据存储方式进行比较。在这里,我们将对SharedPreferences和MMKV进行读写性能的比较。

性能测试方案

  1. 读写大量数据:分别使用SharedPreferences和MMKV进行大量数据的写入和读取操作,记录时间并比较性能表现。
  2. 多线程读写测试:模拟多个线程同时进行读写操作,比较SharedPreferences和MMKV在多线程操作时的性能表现。
  3. 内存占用测试:比较SharedPreferences和MMKV在存储大量数据时的内存占用情况。

性能测试结果分析

通过性能测试,我们得到以下结论:

  1. 读写大量数据:在写入和读取大量数据时,MMKV的性能明显优于SharedPreferences,读写速度更快。
  2. 多线程读写测试:在多线程操作时,MMKV能够更好地保持数据的一致性,不会出现数据安全问题,而SharedPreferences需要考虑同步和锁机制。
  3. 内存占用测试:在存储大量数据时,MMKV的内存占用明显低于SharedPreferences,特别是在大规模数据存储时,MMKV的优势更加明显。

通过性能测试结果分析,可以得出结论:MMKV在性能方面具有明显的优势,包括读写速度更快、多线程操作更稳定、内存占用更低等特点。因此,开发者可以放心地选择MMKV作为数据存储方式,以提升应用的性能表现和用户体验。

结语

MMKV作为一种高性能的跨平台键值存储解决方案,具备许多优势和适用场景。通过对MMKV的特点和使用方法的介绍,我们可以得出以下结论:

  1. 高性能特点:MMKV具有卓越的读写性能,比传统的数据存储方式(如SharedPreferences)更快速有效。它采用了底层的mmap技术和序列化算法优化,以实现更高的读写速度和更低的内存占用。

  2. 适用场景:MMKV特别适用于移动应用开发中需要频繁进行大量数据读写的场景。例如,缓存管理、用户偏好设置、临时数据存储等。无论是小型应用还是大规模数据存储,MMKV都能够提供卓越的性能和稳定性。

因此,我们鼓励开发者积极尝试并采用MMKV作为数据存储解决方案,以提升应用的数据存储效率和性能表现。通过使用MMKV,开发者可以获得更好的用户体验,并提高应用在不同平台上的兼容性和可移植性。

总之,MMKV是一个强大且易于使用的数据存储库,它为移动应用开发者提供了一种高性能的替代方案。希望开发者们能够充分利用MMKV的优势,并将其应用于实际的项目中,以提升应用的数据存储效率和性能表现。

参考链接

https://github.com/Tencent/MMKV

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/679232.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python巧用定理判断素数

目录 判断一个数n是否是素数 求一个数的素因数个数 求大于等于指定数的最小素数 在数论中有三个非常重要的关于素数的定理 1、任何数都可以表示成若干个素数的乘积 2、任意数的一个素因子如果小于根号n,那么另一个与其对应的素因子必然大于根号n。 3、除了2和…

浅谈应该遵守的伦敦银交易规则

做伦敦银投资的朋友应遵守伦敦银交易规则,伦敦银交易规则不是指那些伦敦银交易技巧,而是在这个市场中要遵循的一些约定,下面我们就来讨论一下。 风险管理。风险管理即指投资者控制自己一笔乃至整体交易的风险,没有风险管理意识的投…

JavaSE——方法(1/2)-介绍、方法的各种形式、使用的要求

目录 方法的介绍 方法的其他形式 方法使用的要求 方法的介绍 方法是什么 方法是一种语法结构,它可以把一段代码封装成一个功能,以便重复调用。 方法的完整格式 修饰符 返回值类型 方法名 ( 形参列表 ) { 方法体代码(需要执行的功能代码) return…

OpenCV-36 多边形逼近与凸包

目录 一、多边形的逼近 二、凸包 一、多边形的逼近 findContours后的轮廓信息countours可能过于复杂不平滑,可以用approxPolyDP函数对该多边形曲线做适当近似,这就是轮廓的多边形逼近。 apporxPolyDP就是以多边形去逼近轮廓,采用的是Doug…

面试经典150题——三数之和

​"The road to success and the road to failure are almost exactly the same." - Colin R. Davis 1. 题目描述 2. 题目分析与解析 2.1 思路一——暴力方法 因为三个数相加为0,那么说明其中两个加数的和与另一个加数为相反数则满足题意。所以可以得到…

ClickHouse时区

clickhouse数据库的时间是UTC时间。服务器默认的是上海时间。 sudo vim /etc/clickhouse-server/config.xml clickhouse默认的时区是注释的就是UTC时间 %F 表示日期,格式为 YYYY-MM-DD。%T 表示时间,格式为 HH:MM:SS。 因此,formatDateT…

主干网络篇 | YOLOv5/v7 更换主干网络为 VGG13 / VGG16 / VGG19 | 对比实验必备

论文地址:https://arxiv.org/pdf/1409.1556.pdf 在这项工作中,我们研究了卷积网络深度对其在大规模图像识别环境中准确性的影响。我们的主要贡献是对使用非常小(33)卷积滤波器的架构的不断增加深度的网络进行了彻底评估,这表明通过将深度推进到16-19个权重层,可以在先前…

第72讲后台管理Container布局实现

新建layout目录 登录成功后&#xff0c;跳转layout布局容器页面 login页面&#xff1a; 导入router import router from "/router";登录成功&#xff0c;跳转后台管理页面 选用布局容器&#xff1a; <template><div class"common-layout">…

javaweb物业管理系统jsp项目

文章目录 物业管理系统一、系统演示二、项目介绍三、系统部分功能截图四、部分代码展示五、底部获取项目源码&#xff08;9.9&#xffe5;带走&#xff09; 物业管理系统 可用作javaweb项目、servlet项目、jsp项目的项目设计 一、系统演示 物业管理系统 二、项目介绍 语言&a…

Vue3中Setup概述和使用(三)

一、引入Setup 1、Person.Vue 与Vue3编写简单的App组件(二) 中的区别是&#xff1a;取消data、methods等方法,而是将数据和方法定义全部放进setup中。 <template><div class"person"><h1>姓名:{{name}}</h1><h1>年龄:{{age}}</h…

Acwing---839. 模拟堆

模拟堆 1.题目2.基本思想3.代码实现 1.题目 维护一个集合&#xff0c;初始时集合为空&#xff0c;支持如下几种操作&#xff1a; I x&#xff0c;插入一个数 x&#xff1b;PM&#xff0c;输出当前集合中的最小值&#xff1b;DM&#xff0c;删除当前集合中的最小值&#xff08…

好看的登录界面源码,希望您喜欢

闲来无事&#xff0c;写几个好看的html界面玩一玩&#xff01; 登录界面一&#xff1a; 代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-widt…

MySQL表的基础操作

创建表 create table 表名&#xff08;列名 类型&#xff0c;列名 类型……&#xff09; 注意 1.在进行表操作之前都必须选中数据库 2.表名&#xff0c;列名等一般不可以与关键字相同&#xff0c;如果确定相同&#xff0c;就必须用反引号引住 3.可以使用comment来增加字段说…

c++水仙花数

一.什么是水仙花数 水仙花数是一个三位数它的个位,十位,百位的三次幂相加的和为他本身 例如:1*1*15*5*53*3*3153及153为水仙花数 二.代码 三.样例

98.网游逆向分析与插件开发-网络通信封包解析-定位明文发送数据的关键函数

内容参考于&#xff1a;易道云信息技术研究院VIP课 上一个内容&#xff1a;项目需求与需求拆解 通过上一个内容有了对网络通信架构有一个简单认识了解&#xff0c;对于我们重要的点是 组织数据 到 加密数据之间的过程&#xff0c;这个过程的数据我们是可以看懂的&#xff0c;…

【python5】闭包/装饰器,

文章目录 1.闭包和装饰器&#xff1a;函数里return就是闭包2.解析eeprom&#xff1a;如下是二进制文件&#xff0c;C8是一个字节3.json/configparser/optparse&#xff1a;json.dumps&#xff08;将字典转化为字符串&#xff0c;将json信息写进文件&#xff09;&#xff0c;jso…

华为环网双机接入IPTV网络部署案例

环网双机接入IPTV网络部署案例 组网图形 图2 环网双机场景IPTV基本组网图 方案简介配置注意事项组网需求数据规划配置思路操作步骤配置文件 方案简介 随着IPTV业务的迅速发展&#xff0c;IPTV平台承载的用户也越来越多&#xff0c;用户对IPTV直播业务的可靠性要求越来越高。…

图灵日记--MapSet字符串常量池反射枚举Lambda表达式泛型

目录 搜索树概念实现性能分析和 java 类集的关系 搜索概念及场景模型 Map的使用Map常用方法 Set的说明常见方法说明 哈希表冲突-避免-负载因子调节冲突-解决-闭散列冲突-解决-开散列/哈希桶冲突严重时的解决办法 实现和 java 类集的关系 字符串常量池String对象创建intern方法 …

深入理解Go的垃圾回收机制

导语 如果你是一位Golang的开发者&#xff0c;你一定对于语言特性和详细结构有所了解。但是&#xff0c;你是否曾经停下来深入研究过Golang背后复杂而强大的垃圾回收&#xff08;GC&#xff09;机制&#xff1f;在这篇文章中&#xff0c;我们将具体深入探讨Golang垃圾回收机制…

机器学习系列——(十五)随机森林回归

引言 在机器学习的众多算法中&#xff0c;随机森林以其出色的准确率、对高维数据的处理能力以及对训练数据集的异常值的鲁棒性而广受欢迎。它是一种集成学习方法&#xff0c;通过构建多个决策树来进行预测和分类。本文将重点介绍随机森林在回归问题中的应用&#xff0c;即随机…