微信团队分享:iOS版微信的高性能通用key-value组件技术实践
本文来自微信开发团队guoling的技术分享。
1、前言
本文要分享的是iOS版微信内部正在推广和使用的一个高性能通用key-value 组件的技术实践过程,该组件在微信内部被命名为MMKV(以下简称MMKV)。
MMKV 是基于 mmap 内存映射的 key-value 组件,底层序列化/反序列化使用 protobuf 实现,性能高,稳定性强。希望对于有高性能key-value 组件或类似技术需求的IM同行,能通过本文获得一定的启发。
学习交流:
- 即时通讯开发交流群:320837163[推荐]
- 移动端IM开发入门文章:《新手入门一篇就够:从零开发移动端IM》
(本文同步发布于:http://www.52im.net/thread-1461-1-1.html)
2、MMKV 源起
在 iOS 微信的日常运营中,时不时就会爆发特殊文字引起 iOS 系统的 crash,《微信团队分享:iOS版微信是如何防止特殊字符导致的炸群、APP崩溃的?》一文里面设计的技术方案是在关键代码前后进行计数器的加减,通过检查计数器的异常,来发现引起闪退的异常文字。
《微信团队分享:iOS版微信是如何防止特殊字符导致的炸群、APP崩溃的?》里设计的技术方案大致原理就是:
1)在会话列表、会话界面等有大量 cell 的地方,希望新加的计时器不会影响滑动性能;
2)这些计数器还要永久存储下来——因为闪退随时可能发生。
这就需要一个性能非常高的通用 key-value 存储组件,我们考察了 NSUserDefaults、SQLite 等常见组件,发现都没能满足如此苛刻的性能要求。考虑到这个防 crash 方案最主要的诉求还是实时写入,而 mmap 内存映射文件刚好满足这种需求,我们尝试通过它来实现一套 key-value 组件。
3、MMKV 原理
3.1 内存准备
通过 mmap 内存映射文件,提供一段可供随时写入的内存块,App 只管往里面写数据,由 iOS 负责将内存回写到文件,不必担心 crash 导致数据丢失。
3.2 数据组织
数据序列化方面我们选用 protobuf 协议,pb 在性能和空间占用上都有不错的表现。考虑到我们要提供的是通用 kv 组件,key 可以限定是 string 字符串类型,value 则多种多样(int/bool/double等)。要做到通用的话,考虑将 value 通过 protobuf 协议序列化成统一的内存块(buffer),然后就可以将这些 KV 对象序列化到内存中。
更多有关Protobuf的文章请见:
《强列建议将Protobuf作为你的即时通讯应用数据传输格式》
《全方位评测:Protobuf性能到底有没有比JSON快5倍?》
《一个基于Protocol Buffer的Java代码演示》
《详解如何在NodeJS中使用Google的Protobuf》
3.3 写入优化
标准 protobuf 不提供增量更新的能力,每次写入都必须全量写入。
考虑到主要使用场景是频繁地进行写入更新,我们需要有增量更新的能力:
1)将增量 kv 对象序列化后,直接 append 到内存末尾;
2)这样同一个 key 会有新旧若干份数据,最新的数据在最后;
3)那么只需在程序启动第一次打开 mmkv 时,不断用后读入的 value 替换之前的值,就可以保证数据是最新有效的。
3.4 空间增长
使用 append 实现增量更新带来了一个新的问题,就是不断 append 的话,文件大小会增长得不可控。例如同一个 key 不断更新的话,是可能耗尽几百 M 甚至上 G 空间,而事实上整个 kv 文件就这一个 key,不到 1k 空间就存得下。这明显是不可取的。
我们需要在性能和空间上做个折中:
1)以内存 pagesize 为单位申请空间,在空间用尽之前都是 append 模式;
2)当 append 到文件末尾时,进行文件重整、key 排重,尝试序列化保存排重结果;
3)排重后空间还是不够用的话,将文件扩大一倍,直到空间足够。
3.5 数据有效性
考虑到文件系统、操作系统都有一定的不稳定性,我们另外增加了 crc 校验,对无效数据进行甄别。在 iOS 微信现网环境上,我们观察到有平均约 70w 日次的数据校验不通过。
4、MMKV 使用
4.1 快速上手
MMKV 提供一个全局的实例,可以直接使用:
可以看到,MMKV 在使用上还是比较简单的。如果不同业务需要区别存储,也可以单独创建自己的实例:
4.2 支持的数据类型
支持以下 C 语语言基础类型:
bool、int32、int64、uint32、uint64、float、double
支持以下 ObjC 类型:
NSString、NSData、NSDate
5、MMKV 性能
写了个简单的测试,将 MMKV、NSUserDefaults 的性能进行对比(循环写入1w 次数据,测试环境:iPhone X 256G, iOS 11.2.6,单位:ms)。
可见 MMKV 性能远远优于 iOS 自带的 NSUserDefaults。另外,在测试中发现,NSUserDefaults 在每2-3次测试,就会有1次比较耗时的操作,怀疑是触发了数据 synchronize 重整写入。对比之下,MMKV即使触发数据重整,也保持了性能的稳定高效。
目前 MMKV 已经在鹅厂内部开源(http://git.code.oa.com/wechat-team/mmkv),反馈比较好的话会考虑对外开源。
(原文链接:https://mp.weixin.qq.com/s/cZQ3FQxRJBx4px1woBaasg,本文略有改动)
附录:有关微信、QQ的文章汇总
[1] QQ、微信团队原创技术文章:
《微信团队分享:iOS版微信的高性能通用key-value组件技术实践》
《微信团队分享:iOS版微信是如何防止特殊字符导致的炸群、APP崩溃的?》
《腾讯技术分享:Android手Q的线程死锁监控系统技术实践》
《QQ音乐团队分享:Android中的图片压缩技术详解(上篇)》
《QQ音乐团队分享:Android中的图片压缩技术详解(下篇)》
《腾讯团队分享 :一次手Q聊天界面中图片显示bug的追踪过程分享》
《微信团队分享:微信Android版小视频编码填过的那些坑》
《微信团队披露:微信界面卡死超级bug“15。。。。”的来龙去脉》
《月活8.89亿的超级IM微信是如何进行Android端兼容测试的》
《微信客户端团队负责人技术访谈:如何着手客户端性能监控和优化》
《微信团队原创分享:Android版微信的臃肿之困与模块化实践之路》
《微信团队原创分享:微信客户端SQLite数据库损坏修复实践》
《腾讯原创分享(一):如何大幅提升移动网络下手机QQ的图片传输速度和成功率》
《腾讯原创分享(二):如何大幅压缩移动网络下APP的流量消耗(下篇)》
《腾讯原创分享(二):如何大幅压缩移动网络下APP的流量消耗(上篇)》
《如约而至:微信自用的移动端IM网络层跨平台组件库Mars已正式开源》
《开源libco库:单机千万连接、支撑微信8亿用户的后台框架基石 [源码下载]》
《微信新一代通信安全解决方案:基于TLS1.3的MMTLS详解》
《微信团队原创分享:Android版微信后台保活实战分享(进程保活篇)》
《微信团队原创分享:Android版微信后台保活实战分享(网络保活篇)》
《Android版微信从300KB到30MB的技术演进(PPT讲稿) [附件下载]》
《微信团队原创分享:Android版微信从300KB到30MB的技术演进》
《微信技术总监谈架构:微信之道——大道至简(PPT讲稿) [附件下载]》
《微信海量用户背后的后台系统存储架构(视频+PPT) [附件下载]》
《微信异步化改造实践:8亿月活、单机千万连接背后的后台解决方案》
《架构之道:3个程序员成就微信朋友圈日均10亿发布量[有视频]》
《微信团队原创分享:Android内存泄漏监控和优化技巧总结》
《微信团队原创Android资源混淆工具:AndResGuard [有源码]》
《移动端IM实践:Android版微信如何大幅提升交互性能(一)》
《移动端IM实践:Android版微信如何大幅提升交互性能(二)》
《移动端IM实践:WhatsApp、Line、微信的心跳策略分析》
《移动端IM实践:谷歌消息推送服务(GCM)研究(来自微信)》
《信鸽团队原创:一起走过 iOS10 上消息推送(APNS)的坑》
>> 更多同类文章 ……
[2] 有关QQ、微信的技术故事:
《2017微信数据报告:日活跃用户达9亿、日发消息380亿条》
《技术往事:创业初期的腾讯——16年前的冬天,谁动了马化腾的代码》
《技术往事:史上最全QQ图标变迁过程,追寻IM巨人的演进历史》
《开发往事:深度讲述2010到2015,微信一路风雨的背后》
《开发往事:记录微信3.0版背后的故事(距微信1.0发布9个月时)》
>> 更多同类文章 ……
(本文同步发布于:http://www.52im.net/thread-1461-1-1.html)
微信团队分享:iOS版微信的高性能通用key-value组件技术实践的更多相关文章
- 微信团队分享:iOS版微信是如何防止特殊字符导致的炸群、APP崩溃的?
本文来自微信开发团队yanyang的技术分享. 1.引言 相信大家都遇到过一段特殊文本可以让iOS设备所有app闪退的经历.前段时间大年初一,又出现某个印度语字符引起iOS11系统奔溃,所幸iOS版微 ...
- 微信团队原创分享:iOS版微信的内存监控系统技术实践
本文来自微信开发团队yangyang的技术分享. 一.前言 FOOM(Foreground Out Of Memory),是指App在前台因消耗内存过多引起系统强杀.对用户而言,表现跟crash一样. ...
- 微信团队分享:极致优化,iOS版微信编译速度3倍提升的实践总结
1.引言 岁月真是个养猪场,这几年,人胖了,微信代码也翻了. 记得 14 年转岗来微信时,用自己笔记本编译微信工程才十来分钟.如今用公司配的 17 年款 27-inch iMac 编译要接近半小时:偶 ...
- 微信团队分享:Kotlin渐被认可,Android版微信的技术尝鲜之旅
本文由微信开发团队工程是由“oneliang”原创发表于WeMobileDev公众号,内容稍有改动. 1.引言 Kotlin 是一个用于现代多平台应用的静态编程语言,由 JetBrains 开发( ...
- 腾讯微信被怼,iOS版微信不能打赏了
2017年4月19日,估计很多有着大量粉丝的微信自媒体作者会感到很不爽,因为他们的苹果粉丝再也无法很爽快地.肆意.任性地打赏他们了,按目前iphone手机的占有率,估计打赏率会掉一半以上. 据微信派微 ...
- 通过微信Android和iOS版,看两大系统的差异
由于设计师或者产品经理使用的移动设备大部分是iPhone,所以在做设计时,容易忽略Android和iOS的差异,按照自己的使用习惯进行设计,导致大部分设计师或产品经理做出的设计都是基于iOS规范或习惯 ...
- iOS版微信6.5.21发布 适配iPhone X
昨日,iOS版微信迎来v6.5.21正式版发布,本次升级主要适配iPhone X,在聊天中查找聊天内容时,可以查找交易消息.可以给聊天中的消息设置日期提醒.上一个正式版v6.5.16发布于9月13日, ...
- 解决alert在ios版微信中显示url的问题(重写alert)
为了解决alert在ios版微信中显示url的问题 window.alert = function(name){ var iframe = document.createElement("I ...
- 微信JSSDK分享朋友圈微信自定义分享接口
服务项目 新手技术咨询 企业技术咨询 定制开发 服务说明 QQ有问必答 QQ.微信.电话 微信开发.php开发,网站开发,系统定制,小程序开发 价格说明 200元/月 1000/月 商议 ...
随机推荐
- SSH的简单入门体验(Struts2.1+Spring3.1+Hibernate4.1)- 查询系统(下)
我们继续吧,SSH最大的优点就是实现的系统的松耦合,能够将后台和前台有机的分离开来. 一.目录结构 一个好的程序要有一个好的开始.我们先来看看整个目录结构吧 主要的是三层架构概念,或者说是mvc的概念 ...
- 在css中设置图片的背景图,怎么设置图片纵向拉伸
css中设置背景图拉伸填充,在css2.1之前这个背景的长宽值是不能被修改的. 实际的结果是只能重复显示,可以使用repeat,repeat-x,repeat-y,no-repeat这些属性来控制背景 ...
- Log4Net的WinForm使用
一.Log4Net的WinForm使用 1.首先使用nuget 添加log4Net 到WinForm项目中 log4j每个符号的具体含义:%d %5p %c{1}:%L - %m%n log4j.pr ...
- 搜索引擎--范例:SAE创建新应用,SVN管理代码
最初接触的平台是新浪SAE平台,虽然限制多得要命,速度也不怎么样,但无论怎么样,人家是“免费的”,免费的东西你还想怎么样?是不是? 1:注册登录新浪SAE,这个不用多说,相信你们的智商 2:创建一个新 ...
- Liquibase 快速开始
Step 1 :创建Changelog文件,所有的数据库变动都会保存在Changelog文件中 <?xml version="1.0" encoding="UTF- ...
- Linux下安装Sybase ASE 16
https://jingyan.baidu.com/article/414eccf67281a16b421f0a76.html
- AC日记——Collectors Problem uva 10779
UVA - 10779 思路: 最大流: s向所有的贴纸的种类连边,流量为Bob拥有的数量: 然后,Bob的朋友如果没有这种贴纸,则这种贴纸向bob的朋友连边,容量1: 如果bob的朋友的贴纸很多大于 ...
- [php] 解析JSON字符串
$json_str = '{"thumb":"","photo":[{"url":"557a3d2184db0 ...
- [xunsearch] 在thinkphp中使用xunsearch
file: XunSearchController.class.php <?php namespace Home\Controller; include '/opt/xunsearch/sdk/ ...
- Codeforces 811 A. Vladik and Courtesy
A. Vladik and Courtesy time limit per test 2 seconds memory limit per test 256 megabytes input sta ...