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

news2024/12/25 23:44:14

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;

    @Override
    protected 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.coloradmin.cn/o/1445244.html

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

相关文章

【深度学习每日小知识】全景分割

全景分割 全景分割是一项计算机视觉任务,涉及将图像或视频分割成不同的对象及其各自的部分,并用相应的类别标记每个像素。与传统的语义分割相比,它是一种更全面的图像分割方法,传统的语义分割仅将图像划分为类别,而不…

浅谈路由器交换结构

一、路由器技术概述 路由器(Router)是连接两个或多个网络的硬件设备,在网络间起网关的作用,是读取每一个数据包中的地址然后决定如何传送的专用智能性的网络设备。它能够理解不同的协议,例如某个局域网使用的以太网协议…

leetcode(矩阵)74. 搜索二维矩阵(C++详细解释)DAY7

文章目录 1.题目示例提示 2.解答思路3.实现代码结果 4.总结 1.题目 给你一个满足下述两条属性的 m x n 整数矩阵: 每行中的整数从左到右按非严格递增顺序排列。每行的第一个整数大于前一行的最后一个整数。 给你一个整数 target ,如果 target 在矩阵中…

《CSS 简易速速上手小册》第2章:CSS 布局与定位(2024 最新版)

文章目录 2.1 Flexbox:灵活的布局解决方案2.1.1 基础知识2.1.2 重点案例:创建一个响应式导航菜单2.1.3 拓展案例 1:卡片布局2.1.4 拓展案例 2:中心对齐的登录表单 2.2 Grid 布局:网格系统的魔力2.2.1 基础知识2.2.2 重…

Apache网站部署

站点添加及linux防火墙和selinux启动和停止 apache站点添加 linux系统防火墙和selinux起停 1、防火墙firewall操作 查看防火墙的状态,如下(默认开启): systemctl status firewalld 关闭服务 systemctl stop firewalld 关闭…

PySpark(四)PySpark SQL、Catalyst优化器、Spark SQL的执行流程、Spark新特性

目录 PySpark SQL 基础 SparkSession对象 DataFrame入门 DataFrame构建 DataFrame代码风格 DSL SQL SparkSQL Shuffle 分区数目 DataFrame数据写出 Spark UDF Catalyst优化器 Spark SQL的执行流程 Spark新特性 自适应查询(SparkSQL) 动态合并 动态调整Join策略 …

【数据结构】哈希表的开散列和闭散列模拟

哈希思想 在顺序和树状结构中,元素的存储与其存储位置之间是没有对应关系,因此在查找一个元素时,必须要经过多次的比较。 顺序查找的时间复杂度为0(N),树的查找时间复杂度为log(N)。 我们最希望的搜索方式:通过元素…

Mybatis Day02

增删改查 环境准备 创建一个emp表创建一个新的springboot工程,选择mysql、lombok、mybatis依赖application.properties中引入数据库连接信息创建对应的实体类Emp准备Mapper接口EmpMapper,mapper代表程序运行时自动创建接口的代理对象,并放入…

Linux下的容器化技术:从入门到实践

你是否曾经遇到过这样的困境:在不同的环境中部署应用程序时,总是因为各种依赖关系和环境配置问题而头痛不已?如果有的话,那么容器化技术将是你的救星!在Linux系统下,容器化技术以其轻量级、隔离性和可移植性…

蓝桥杯每日一题------背包问题(二)

前言 本次讲解背包问题的一些延申问题,新的知识点主要涉及到二进制优化,单调队列优化DP,树形DP等。 多重背包 原始做法 多重背包的题意处在01背包和完全背包之间,因为对于每一个物品它规定了可选的个数,那么可以考虑…

Spring 如何解决循环依赖?Spring三级缓存

什么是循环依赖 说白是一个或多个对象实例之间存在直接或间接的依赖关系,这种依赖关系构成了构成一个环形调用。 自己依赖自己 两个对象间的依赖关系 多个对象间的依赖关系 Spring出现循环依赖的场景 单例的setter注入 Service public class A {Resourceprivate…

【精选】java多态进阶——多态练习测试

🍬 博主介绍👨‍🎓 博主介绍:大家好,我是 hacker-routing ,很高兴认识大家~ ✨主攻领域:【渗透领域】【应急响应】 【python】 【VulnHub靶场复现】【面试分析】 🎉点赞➕评论➕收藏…

InternLM大模型实战-4.XTuner大模型低成本微调实战

文章目录 前言笔记正文XTuner支持模型和数据集 微调原理跟随文档学习快速上手自定义微调准备数据准备配置文件 MS-Agent微调 前言 本文是对于InternLM全链路开源体系系列课程的学习笔记。【XTuner 大模型单卡低成本微调实战】 https://www.bilibili.com/video/BV1yK4y1B75J/?…

【MySQL进阶之路】生产案例:大量数据刷盘导致的数据库性能抖动问题优化

欢迎关注公众号(通过文章导读关注:【11来了】),及时收到 AI 前沿项目工具及新技术的推送! 在我后台回复 「资料」 可领取编程高频电子书! 在我后台回复「面试」可领取硬核面试笔记! 文章导读地址…

从汇编角度解释线程间互斥-mutex互斥锁与lock_guard的使用

多线程并发的竞态问题 我们创建三个线程同时进行购票&#xff0c;代码如下 #include<iostream> #include<thread> #include<list> using namespace std; //总票数 int ticketCount100; //售票线程 void sellTicket(int idx) {while(ticketCount>0){cou…

从零开始实现消息队列(二)

从零开始实现消息队列 .核心API交换机类型持久化网络通信Connection和Channel 消息应答模块划分 . 核心API 对于Broker来说,要实现以下核心API,通过这些API来实现消息队列的基本功能. 创建队列(queueDeclare)销毁队列(queueDelete)创建交换机(exchangeDeclare)销毁交换机(exc…

第4集《佛说四十二章经》

请大家打开讲议第四面&#xff0c;第一章&#xff0c;出家证果。 佛言&#xff1a;辞亲出家&#xff0c;识心达本&#xff0c;解无为法&#xff0c;名曰沙门。 在经文的刚开始啊&#xff0c;佛陀把修道的沙门提出了两个基本的条件&#xff1a; 第一个是辞亲出家&#xff0c;…

【Linux技术宝典】Linux入门:揭开Linux的神秘面纱

文章目录 官网Linux 环境的搭建方式一、什么是Linux&#xff1f;二、Linux的起源与发展三、Linux的核心组件四、Linux企业应用现状五、Linux的发行版本六、为什么选择Linux&#xff1f;七、总结 Linux&#xff0c;一个在全球范围内广泛应用的开源操作系统&#xff0c;近年来越来…

MySQL数据库-索引概念及其数据结构、覆盖索引与回表查询关联、超大分页解决思路

索引是帮助mysql高效获取数据的数据结构,主要用来提高检索的效率,降低数据库的IO成本(输入输出成本&#xff08;Input-Output Cost&#xff09;),同时通过索引对数据进行排序也能降低数据排序的成本,降低了CPU的消耗。 Mysql的默认存储引擎InnoDB&#xff0c;InnoDB采用的B树的…

代码随想录算法训练营第四十九天(动态规划篇)| 474. 一和零, 完全背包理论基础

474. 一和零 题目链接&#xff1a;https://leetcode.cn/problems/ones-and-zeroes/submissions/501607337/ 思路 之前的背包问题中&#xff0c;我们对背包的限制是容量&#xff0c;即每个背包装的物品的重量和不超过给定容量&#xff0c;这道题的限制是0和1的个数&#xff0…