MMKV组件实现原理以及和SharedPreferences的比较(二)

本文主要分析了Android中MMKV的数据结构,它以MMKV.default文件保存,总长度4字节。使用变长编码使key和value长度为1 - 5字节,底层用protobuf实现序列化和反序列化。写入方式为增量写入,还介绍了解决文件过大的方法。MMKV具有防止数据丢失、精简数据、增量更新等优势。
MMKV数据结构
  • 上面提到的SharedPreferences使用的是xml来进行文件存储的
<map>
    <int name = "4970" value="4970"/>
    <int name = "4971" value="4971"/>
    <int name = "4972" value="4972"/>
    <int name = "4973" value="4973"/>
    <int name = "4974" value="4974"/>
    <int name = "4975" value="4975"/>
  • 而MMKV的数据结构是:
    在这里插入图片描述

    • 将这个数据结构保存为MMKV.default文件,总长度为4字节
      在这里插入图片描述
使用这种数据结构的原因:
  • 全是数字表示,直接将xml中的多余部分省略,数据量越小,操作的速度越快
  • key和value的长度可以为1~5个字节
如何做到key和value长度为1~5个字节
  • 使用变长编码
变长编码实现原理:
  • 底层序列化和反序列化使用protobuf实现,性能高,稳定性强
  • 数据量表示会比JSON和xml小很多
  • 编码示例:
进制数值
16进制0x7f
10进制127
2进制0111 1111
  • 写入: 0111 1111
进制数值
16进制0x80
10进制128
2进制1000 0000
  • 写入:0000 0001

  • 计算写入值的方式:

    • 机组中的变长编码将第一位设置为标志位:表示符号
    • 比如:1000 0000
    • 1.去掉符号位剩下 000 0000 一会放到结果的后面
    • 2.将1000 0000 右移7位得到 0000 0001
    • 3.0000 0001去掉第一位的符号位得000 0001 一会放到结果的前面
    • 4.结果:0000 0000 1000 0000
写入方式:增量写入
  • 不管key是否重复,直接将数据追加在前数据后面即可
解决文件越来越大的问题:

全量写入:当文件大小不够,需要进行全量写入,将数据去掉重复key之后,如果文件大小满足写入的数据大小,则可以直接更新全量写入,否则需要扩容(根据平均每个K-V大小计算未来可能需要的文件大小来进行扩容,防止经常性全量写入)

  • 去重的工作交给map去做即可,如果一直提交数据没有重复的数据就需要将进行扩容
MMKV的优势
  • mmap防止数据丢失,提高读写效率
  • 精简数据,以最少的数据量表示最多的信息,减少数据的大小
  • 增量更新,避免每次进行相对增量来说数据量的全量写入
Android中实现MMKV
extern "C"
JNIEXPORT void JNICALL
Java_com_wjx_android_mymmkv_MMKV_writeTest(JNIEnv *env, jobject instance) {
    std::string file = "/sdcard/wjx.txt";
    m_fd = open(file.c_str(), O_RDWR | O_CREAT, S_IRWXU);
    m_size = getpagesize();
    ftruncate(m_fd, m_size);
    m_ptr = (int8_t *) mmap(0, m_size, PROT_READ |PROT_WRITE, MAP_SHARED, m_fd, 0);
    std::string data("wjx");
    //将data的data.size()个数据拷贝到m_ptr
    memcpy(m_ptr, data.data(), data.size());
}
extern "C"
JNIEXPORT jstring JNICALL
Java_com_wjx_android_mymmkv_MMKV_readTest(JNIEnv *env, jobject instance) {
    char *buf = static_cast<char *>(malloc(33));
    memcpy(buf, m_ptr, 33);
    std:string result(buf);
    munmap(m_ptr, m_size);
    close(m_fd);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wjxbless

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值