MMKV 基于 mmap 的高性能通用 key-value 组件

2024-02-17 17:08

本文主要是介绍MMKV 基于 mmap 的高性能通用 key-value 组件,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

学前介绍

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

官方MMKV地址


为什么要替代SharedPreferences?

  • 1,数据加密。

在 Android 环境里,数据加密是非常必须的,SP实际上是把键值对放到本地文件中进行
存储。如果要保证数据安全需要自己加密,MMKV 使用了 AES CFB-128 算法来加密/解密。

  • 2,多进程共享。

系统自带的 SharedPreferences 对多进程的支持不好。现有基于 ContentProvider 封装的实现,虽然多进程是支持了,但是性能低下,经常导致 ANR。考虑到 mmap 共享内存本质上是多进程共享的,MMKV 在这个基础上,深入挖掘了 Android 系统的能力,提供了可能是业界最高效的多进
程数据共享组件。

  • 3,匿名内存。

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

  • 4,效率更高。

MMKV 使用protobuf进行序列化和反序列化,比起SP的xml存放方式,更加高效。可以看看下面的博文。
源码解析SharedPreferences你不知道的缺点

  • 5,支持从 SP迁移,

如果你之前项目里面都是使用SP,现在想改为使用MMKV,只需几行代码即可将之前的SP实现迁移到MMKV。

学习内容:

MMKV是基于mmap来实现的,所以mmap是关键。
为了讲清mmap的原理我们首先需要了解一点基础知识。

  • 物理内存
    真实的硬件设备(内存条)。容量较小。
  • 虚拟内存
    利用磁盘空间虚拟出的一块逻辑内存,用作虚拟内存的磁盘空间被称为交换空间。为了满足物理内存的不足而提出的策略)
int a = 10;
int *p = &a;

大家看上面的代码,是不是特别简单,但我问个问题,这行代码在运行的时候p指向的是物理内存还是虚拟内存。答案是 虚拟内存
接下来就要解释为什么?这就要涉及到MMU
MMU中文名是内存管理单元,有时称作分页内存管理单元,主要用来管理虚拟存储器、物理存储器的控制线路,同时也负责虚拟地址映射为物理地址,以及提供硬件机制的内存访问授权、多任务多进程操作系统。
在这里插入图片描述
linux使用MMU的机器都采用分页机制。虚拟地址空间以为单位进行划分,而相应的物理地址空间也被划分,其使用的单位称为页帧,页帧和页必须保持相同,因为内存与外部存储器之间的传输是以页为单位进行传输的。​虚拟内存的哪个页面映射到物理内存的哪个页帧是通过页表(Page Table)来描述的页表保存在物理内存中。
这里还要讲一下交换区的概念:
实际上就是一块磁盘空间(硬盘空间)。虚拟内存与物理内存映射的时候,是将虚拟内存的代码放到交换区中,以后在CPU想要执行相关的指令或者数据时,如果内存中没有,先去交换区将需要的指令与数据映射到物理内存,然后CPU再执行,而一个进程中不可能全部的代码会同时运行,所以在同一时间,每次只有进程的少部分代码会在物理内存中运行 ,大部分代码依然位于磁盘中(存储器硬盘)。

交换区里面存放的是大部分的可执行代码与数据。而物理内存中,执行的是少部分的可执行代码与数据,其它未执行的大部分代码都在磁盘/硬盘中。

那么此时就需要从交换区获取程序的代码,将它拿到物理内存执行。那么一次拿多少代码过来呢?这是一个问题!

为了CPU的高效执行以及方便的内存管理,每次需要拿一个页的代码。这个页,指的是一段连续的存储空间(常见的是4Kb),也叫作块。

这里我们稍微扩充一下:Intent 是可以传递值的,那这个传值的大小是多大呢?

1M-8k = 2k 这里为什么要减2k 是因为 这里面存放了一些附加信息比如信息头。

终于前期的铺垫终于讲完了,但你肯定疑惑的摸不着头脑,这跟我要学的mmap又什么瓜系呢?

其实mmap就是一种内存映射文件的方法,即将一个文件或者其它对象映射到进程的地址空间,实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系。
Linux的内存分用户空间跟内核空间,同时页表有也分两类,用户空间页表跟内核空间页表,每个进程有一个用户空间页表,但是系统只有一个内核空间页表。
而Binder mmap的关键是:更新用户空间对应的页表的同时也同步映射内核页表,让两个页表都指向同一块地址,这样一来,数据只需要从A进程的用户空间,直接拷贝到B所对应的内核空间,而B所对应的内核空间在B进程的用户空间也有相应的映射,这样就无需从内核拷贝到用户空间了。

  • copy_from_user() //将数据从用户空间拷贝到内核空间
  • copy_to_user() //将数据从内核空间拷贝到用户空间
    mmap大致流程如下图:
    在这里插入图片描述

学习产出:

DEMO

这篇关于MMKV 基于 mmap 的高性能通用 key-value 组件的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/718448

相关文章

Vue3组件中getCurrentInstance()获取App实例,但是返回null的解决方案

《Vue3组件中getCurrentInstance()获取App实例,但是返回null的解决方案》:本文主要介绍Vue3组件中getCurrentInstance()获取App实例,但是返回nu... 目录vue3组件中getCurrentInstajavascriptnce()获取App实例,但是返回n

SpringQuartz定时任务核心组件JobDetail与Trigger配置

《SpringQuartz定时任务核心组件JobDetail与Trigger配置》Spring框架与Quartz调度器的集成提供了强大而灵活的定时任务解决方案,本文主要介绍了SpringQuartz定... 目录引言一、Spring Quartz基础架构1.1 核心组件概述1.2 Spring集成优势二、J

Java枚举类实现Key-Value映射的多种实现方式

《Java枚举类实现Key-Value映射的多种实现方式》在Java开发中,枚举(Enum)是一种特殊的类,本文将详细介绍Java枚举类实现key-value映射的多种方式,有需要的小伙伴可以根据需要... 目录前言一、基础实现方式1.1 为枚举添加属性和构造方法二、http://www.cppcns.co

使用Java实现通用树形结构构建工具类

《使用Java实现通用树形结构构建工具类》这篇文章主要为大家详细介绍了如何使用Java实现通用树形结构构建工具类,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录完整代码一、设计思想与核心功能二、核心实现原理1. 数据结构准备阶段2. 循环依赖检测算法3. 树形结构构建4. 搜索子

Vue中组件之间传值的六种方式(完整版)

《Vue中组件之间传值的六种方式(完整版)》组件是vue.js最强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互引用,针对不同的使用场景,如何选择行之有效的通信方式... 目录前言方法一、props/$emit1.父组件向子组件传值2.子组件向父组件传值(通过事件形式)方

如何解决mysql出现Incorrect string value for column ‘表项‘ at row 1错误问题

《如何解决mysql出现Incorrectstringvalueforcolumn‘表项‘atrow1错误问题》:本文主要介绍如何解决mysql出现Incorrectstringv... 目录mysql出现Incorrect string value for column ‘表项‘ at row 1错误报错

Spring组件初始化扩展点BeanPostProcessor的作用详解

《Spring组件初始化扩展点BeanPostProcessor的作用详解》本文通过实战案例和常见应用场景详细介绍了BeanPostProcessor的使用,并强调了其在Spring扩展中的重要性,感... 目录一、概述二、BeanPostProcessor的作用三、核心方法解析1、postProcessB

kotlin中的行为组件及高级用法

《kotlin中的行为组件及高级用法》Jetpack中的四大行为组件:WorkManager、DataBinding、Coroutines和Lifecycle,分别解决了后台任务调度、数据驱动UI、异... 目录WorkManager工作原理最佳实践Data Binding工作原理进阶技巧Coroutine

MySQL中Next-Key Lock底层原理实现

《MySQL中Next-KeyLock底层原理实现》Next-KeyLock是MySQLInnoDB存储引擎中的一种锁机制,结合记录锁和间隙锁,用于高效并发控制并避免幻读,本文主要介绍了MySQL中... 目录一、Next-Key Lock 的定义与作用二、底层原理三、源代码解析四、总结Next-Key L

Vue项目的甘特图组件之dhtmlx-gantt使用教程和实现效果展示(推荐)

《Vue项目的甘特图组件之dhtmlx-gantt使用教程和实现效果展示(推荐)》文章介绍了如何使用dhtmlx-gantt组件来实现公司的甘特图需求,并提供了一个简单的Vue组件示例,文章还分享了一... 目录一、首先 npm 安装插件二、创建一个vue组件三、业务页面内 引用自定义组件:四、dhtmlx