<aside> 💡 似乎现在又有了点时间,继续更吧。其实回来发现 MMKV 增加了一些安卓多线程的东西,感觉可以再展开讲讲(饼越来越大了)

</aside>

MMKV 是🐧厂开源的一个移动端高性能 KV 数据持久化组件,我来详细讲解一下 MMKV 高性能的几大原因。

至于有多高性能呢,参考下图:

为什么是 MMKV

因为我本来想写一个关于性能优化的操作手册 / 大全,但是个人感觉这种东西应该有一个实例来体现一个渐进式性能优化的过程才比较好,所以我就到处找某个实例。最后我发现了这个东西,感觉里面有很多东西可以讲一讲,而且还涉及到了一些操作系统底层的东西,和前端领域可以说是毫无关系了...不过正好因为毫无关系,可以屏蔽读者理解时的一些额外认知干扰,而更加去聚焦优化本身。我会尽量讲的通俗易懂,并且穿插一些个人的思考。

mmap

我们经常会听说 mmap 比传统 read / write 的性能要好很多,但是为什么呢?因为前者应用了虚拟内存技术,将外存的空间映射到一块虚拟内存的地址上,操作基本上等同于内存操作(同时通过脏页回写来保证数据更新到外存),而后者则是要走 I/O(需要经过文件系统,但有些时候不会)。

我们先来讲一下磁盘的两个缓存机制—— Buffer Cache 和 Page Cache,简单说来,Page cache 用来缓存文件数据,Buffer cache 用来缓存磁盘数据。

Buffer Cache 以块形式缓冲了块设备的操作,定时或手动的同步到硬盘,它是为了缓冲写操作然后一次性将很多改动写入硬盘,避免频繁写硬盘,提高写入效率。

Page Cache 以页面形式缓存了文件系统的文件,给需要使用的程序读取,它是为了给读操作提供缓冲,避免频繁读硬盘,提高读取效率。

然后我们再来讲一下虚拟内存,从它的诞生原因说起,实际上,原先只有物理内存的时期,如果打开一个应用,那么需要将应用所有文件从外存转移到物理内存里,但这样初始化起来效果很差,而且还很容易存在物理内存空间不够的情况(如果是前端同学可能知道 Webpack 分包懒加载之类的优化方案,实际上他们也是为了解决 TTI 和应用初始化速度的问题)。

于是后来人们引入的了虚拟内存技术,应用初始化时只加载常用功能和主要功能在物理内存,而一些非常用功能会放在虚拟内存中,所以我们可以感受到当一个应用使用了一个不常用功能后,会有一些明显的卡顿,这很可能因为该功能启动后,虚拟内存和物理内存进行了交换(但交换过程极快),影响这个交换速度的主要因素还是磁盘的 I/O 速度。

而 mmap 的过程相当于:虚拟内存地址空间 -> Page Cache -> 磁盘文件

protobuf

Protocol Buffers 是一种序列化数据结构的协议(二进制格式)。目前被发扬广大在各种 RPC 传输协议中,可以理解为另一个次元的 JSON Schema。

大量实践表明 Protobuf 比 JSON、XML 性能更好,而且可维护性更优、尺寸更小(理论上 Protocol buffers 的传输效率比 JSON 快 6 倍)。基于这些特性,Protobuf 在移动端的表现就更值得关注了,因为移动端场景下尺寸与效率会更加严苛且两者也更难以平衡。

但是 protobuf 的缺点也是有的,其可读性明显很低(而且关于文本协议和二进制协议,我自己的观点和 *TAOUP* 里的作者关于此的观点几乎保持一致),而 JSON 的结构简单,易于开发者阅读和分析,而且社区实践也比 JSON 少很多,这样的结果就是有关问题的解决方案的检索也会有一些困难。