2017GMTC 性能优化

性能优化专场一共有四场分享,包括“Instagram Direct ⾼性能聊天产品”, “⼿淘iOS性能优化探索”,“滴滴出⾏ iOS 端瘦身实践”和“微信 SQLite 数据库 损坏恢复实践”,除了微信的这个议题,其他三场都现场听了。

Instagram Direct ⾼性能聊天产品

这个演讲个人感觉是两天里面听到的比较好的一次,PPT的结构比较清晰,不会包含太过细节的内容,主题明确,演讲的时候靠演讲本身来阐述细节。

这个议题的主题是“高效可靠的数据端到端传输”,通过这个议题,让大家可以了解:移动应用如何应对不稳定的网络状况,实现信息的稳定传输;如何确保信息的有序传播;如何将复杂的重试机制和应用层开发隔离开来。


Instagram 是一个以图片和视频为核心的社区,用户以年轻人为主,月活达7亿,而Direct是Instagram旗下的一款聊天产品,月活为3.75亿。跟Facebook一样,IM都被独立出来,再想想国内的微信,IM本身的在移动互联网的重要性可见一斑,这也是阿里这么执着的往这个方向发展这么多年的一个原因吧(似乎最近消停了很多)。

言归正传,Direct作为一款新的产品,在两年的时间内用户规模增长达4亿,与之带来的是新功能的不断增加,以及团队规模的不断扩大。这也导致了一个结果就是开发的模式,由一个小的负责多个功能的单平台团队的开发模式,转变成一个团队专注于多个平台的单个功能。这一点跟我们现在的开发模式很像,比如Viz组就负责iOS和Android两块所有的Widget的开发。这也是因为当系统本身业务逻辑越来越复杂,功能模块之间的区分度越来越大的一个必然的结果。

第一部分:前端架构

p6

Direct产品作为一款短消息应用,对“实时性”的要求非常高,哪怕是滑动时稍微卡一点,日活量就会有显著的下降;产品越来越复杂,团队的规模越来越大,随之而来的就是如何确保代码本身的可维护性,特别是当新人加入团队的时候,如何使新人更容易的快速掌握代码;敏捷开发模式下对功能的快速迭代要求很高,这就需要我们的产品技术架构能够适应功能的随时修改和增减。这些都是Direct遇到的比较棘手的问题。

p7

针对前面提到的三个问题,Direct相应的对策分别是:首先是使用纯Native开发来确保产品的性能达到最优,这里对开发代价本身的敏感度就降低了,跟我们自己的产品一样,对产品本身运行的性能要求很高,决定了我们要尽可能的使用Native的开发方式来充分优化产品的性能;代码模块化,压缩单个代码的长度,使代码简单清晰,这一点上我们的产品做得还不够,基本各个功能模块的耦合度过大,也有部分代码的长度过长,现在导致维护起来的成本也越来越大;使用信息流模式让信息在不同模块之间流动,使得测试和调试更加顺畅。

AB测试:对于存在多种方案面临选择时,同时面向客户,通过手机用户体验数据和业务数据,最终评估出最好的版本正式采用。AB测试多用在UI和流程方面,特别是主观性偏强的功能模块,难以通过讨论做出决策时,让终端用户来做出这个选择。

p9

这个信息流图是相对高级的模块区分,其中服务层是连接界面与基础功能模块的关键。从界面产生的操作,通过从服务层相应的服务实现

p10

作为一款聊天产品,最主要的问题就是列表过长,可以看微信就是一个直接的例子:在消息界面,存在着你和朋友聊天的列表,各种公众号的信息,各种群的信息等等。Direct也类似,这会导致处理这个长列表的代码会过于庞大,因为消息的类型多样,也会使代码过于复杂。

p11

Direct采取的应对是切分长列表类,将不同的消息单独处理,使用独立的Section Controller

p12

经典的MVC模式的最主要的问题就是Controller过于臃肿,针对这个问题,在前端开发领域下发展出了多种不同的进阶形式,比如MVP和MVVM:

MVVM:Model(数据访问层),View(UI界面),ViewModel(View的抽象,负责VM之间的信息转换,将View的Command传送到Model,iOS中使用KVO或Notification技术达到这种效果)

Direct针对长列表问题又引入了MVVS这个模式,其实就是讲每一个消息类型分别做MVVM,等于是多加了一层,我们可以参看下面的实例对照

p13-15

采用这种架构后,我们可以确保:每个模块的责任明确,避免臃肿;每一条新消息进入,只需要增加一个Section Controller,更新一个Cell,提高刷新效率和响应速度;如果需要添加一个新消息类型,就直接增加一套MVVS,不用改动其他的代码;克制团队暴兵,容易实现功能迭代

第二部分:消息重试机制

移动App的使用场景经常存在网络不稳定,或者没有网络的情况,这就导致了“如何确保重要信息的稳定传输”成为了提升用户体验的关键。总结而言,聊天产品的设计需求,可以包括:

p17

这里有意思的是“用户感知到的消息发送速度”,用户不仅仅会在意接收到对方消息的速度,对自己发出消息的速度的感知也很强烈。所以一个点就是当用户发出消息时,瞬间展示为正常发送状态,只有在发送失败的时候再更新,这样让用户的体验更加顺畅,而不需要让用户感知到发送的过程。

根据前述的移动环境下的网络不稳定,消息的发送有可能失败,比如当:服务器宕机了,信号不稳定,没有信号等。这种情况下,为保证用户体验的顺畅,我们需要提供“自动重试”的功能。对于聊天产品,让用户感知到消息发送的失败是一件特别严重的事,我们应该尽可能的避免这种情况的发生。

p19

自动重试针对的是随机性的不确定消息传输失败,简单的通过一次重试,就会显著的提高消息发送的成功率。

p20

这是Direct的单个消息重试机制,设置了上限五次。个人感觉文本信息可以重复多次,图片和视频其实两三次就够了,因为图片视频本身的传输时间过长,加上重试后,确认成功的时间可能拖得太长了。

p21

在消息重试机制中一个很重要的问题是如何保证消息发送序列的一致性,Direct这里采用的是单队列的形式,只有前面的消息发送成功后才继续发送后续的消息。(?这里没有并行发送的问题,是因为一个对话信息流相对比较简单,数据量不会过大吗)

p22

我们知道通常的场景是多个对话同时存在,每个对话对用有一个消息队列,这样可以避免不同对话间消息的相对独立。图片和视频与普通的消息不太一样,它们本身体量较大,又需要预处理比如压缩编码等,并且对上下文不如消息敏感,所以确保它们能够迅速的发送出去比保持队列的顺序更加重要。Direct这里采用的是将他们统一发入了一个多媒体队列中。

p23

自动重试直接的会导致更多的CPU和网络资源的占用,因此需要考虑重试的时机。这里总结了Direct实现自动重试的一些时机,其中有一点就是:自动重试只是针对随机性的不确定的消息失败,对于确定性的失败,重试也是失败,是没有意义的。

p24

图片视频的机制与消息稍有不同,因为本身体量过大,所以需要限制同时传送的数量,避免资源占用过多。

p25

Direct里还有一个有趣的问题是多账号系统的存在,出于个人隐私和不同朋友圈的考虑,一个用户可能拥有多个账号,如果将朋友账号里的消息发送到了亲友账号里,可能就会有点尴尬了。Direct这里采用的是在账户切换过程时,暂停消息发送,也就是你的消息只有在你当前账号Active的时候才可以发送。(为不同账号提供不同的session来区分不是更好吗?)

Q&A

1)图片的压缩比例以及重传的分析

图片压缩的比例一般是 50%-80%,压缩后对用户的体验影响不大,除非是那种像素特高的高端手机。如果一个版本更新后重传量暴增,这个八成是代码的问题,而不是网络的问题,对于分析重传的效率,会通过后台的日志记录来分析。

2)当团队由小团队变成大团队,历史存量代码过大的时候,如何实现组件化

Direct就存在这个问题,存量代码有非常巨大的类:针对这种问题,解决过程一般都是非常有挑战的,比如Direct的消息列,大概3500+行的代码,由一个工程师到三四个工程师同时工作。在更新的过程中,会保留旧的代码,同时运行新的代码,比如从1%的用户开始,通过检测分析这1%的用户的使用情况,即使发现bug,再慢慢的推广到所有的用户。使用这种循序渐进的方法来避免初期不稳定的影响范围。(跟AB测试有点类似)

对于代码划分的粒度,Direct里开始的时候是从UI无关的代码开始,并且限制每个类不超过300行(~这种粒度比我们的细多了)

3)Direct从十几个工程师到七十几个工程师是如何进行职能划分的

按照不同的业务模块划分,比如广告、图片等,每个业务模块有独立的PM,一般开发的过程是代码逐步整合,但是等功能完善后再逐步放开,这个节点是等待内测完成,虽然代码可能已经存在于正式产品中。

4)产品的功能越来越多的时候,按照功能划分,如何处理跨平台问题

尽可能的保持大的方向在不同平台上一致,小的地方根据不同平台的特性保证高效率,比如iOS会选Sqllite

5)一周发布一次的频率,如何保证开发的质量

代码的单元测试(对核心功能测试,UI相对少);灰度的小开关(虽然一周发一次,但是四周后才打开);内部会有测试的反馈意见;QA相对测试,基于自动化测试,以及内测;其实很多时候,发现的问题就是产品的设计本身的问题

6)Direct产品指标

Crash率是关键指标,在内测阶段,大的bug会作为指标,然后对于Direct,日活率,月活率,接受率,发送率等等

7)新功能如果不及预期,是否会砍掉

大部分功能是一个工程师单独完成,大的功能,一般会区分iOS和Android独立开发。上线后发现的bug肯定会及时修改,但如果是产品设计的问题,就会砍掉


手淘iOS性能优化探索

这个议题主要介绍了手机淘宝iOS性能优化的一些工作,针对移动开发性能优化和运维相关提供一些新的思路。


由表象的终端用户感受到的问题,到在业务流程角度需要考虑排查的性能问题

p4

手淘从技术上的研发流程角度,将问题划分为这四个阶段。

研发架构支撑

p5

其实我们的产品也很类似,我们的启动过程也非常复杂,简单的看我们的Delegate和Context相关的代码量就是一个巨量,并且我们也在启动过程中绑定了很多的功能模块,像Authenticaiton就有很多种。这个结果也是我们在开发的过程中,不停的“无节制”的添加功能导致的,手淘的这些问题我们的产品也基本都存在。手淘的设计目标,简单的就是说要实现启动任务的松耦合,实现高并发,提高性能,再通过线上服务器端解决使用中的问题。除了这条线上控制,其他的三点我们的产品也基本都可以利用。


p6

因为每个具体用户的使用习惯不同,并且不像我们2B的产品,实现可以知道具体用户的使用场景,比如不同职务会看不同的报表,像手淘这种2C的产品,只有用户使用后才能知道用户的使用场景和习惯。所以这里“自学习启动任务”是要求手淘可以根据用户的使用习惯,调整APP启动时,不同任务的优先级。另外,首页启动的优先级最高,你不可能让用户对着启动页看上半天,可以通过Cache先将首页渲染出来,再通过其他的线程逐步更新首页内容。

集成数据卡口

p8

主要是介绍了API调用的时候,如何去统计和定位具体函数的耗时,会细节到汇编代码的层次去分析。

性能无痕度量


p18

这里介绍的一个主要问题是:如何判定屏幕渲染已经完成?

p19

我们不能够以“viewDidAppear”来判定页面已经展示,因为屏幕的渲染进程经常会用到异步的回调渲染,相反的我们应该通过用户的真实体验来判定页面加载完成:

p23-24

不同机型的数据也是不同的,所以除了产品本身,运行的设备对产品性能的影响也是巨大的。

线上排查工具

p26

苹果的Instrument是给开发人员使用的性能排查的工具,我们也都应该使用过它排查过memory leak以及memory的使用瓶颈。这里手淘主要介绍了他们自己的一个线上的Instrument:tbinstrument

p29

设计的思路主要是服务器通过指令来收集线上app的线程信息,在后台进行分析。(什么时候开源?)

Q&A

1)PPI的要求

最低60帧,即使是低端设备

2)Web界面如何监控

像素点采集,因为web不够稳定,所以对于web的采样周期会相应变长

3)手淘Crash后,重启会有弹框进行修复,这里面做了什么

因为这些Crash大多数都是个别人存在的偶然性问题,而在测试过程中并没有发现,这个原因很大可能是某些数据被破坏,导致数据不完整,这时候删除缓存的数据,重新下载和生成新的数据,基本上会解决Crash的问题。

4)自学习启动的优化参数标准

同样的机器,即使运行同样的任务,可能结果都不一样,这是因为机器本身随着使用时间和方式的不同,会导致机器本身性能的差别


滴滴出⾏ iOS 端瘦身实践

在听这个议题的时候,我们正好遇到有客户抱怨我们的APP过大,我们现在的DMG编完的app大概为300M+,这里面的最主要的问题是我们的framework同时支持了Simulator和Device,以及32位和64位的机器,通过脚本我们删除了多余的支持内容后,如果只确保生成具体Device的编译文件,我们生成的APP大概为100M+的水平。当然,还是很大~~ 后面想要继续瘦身的话,只能从代码层面以及图片资源方面下手了。

对于滴滴来说,存在同样的问题,APP经过长期的产品迭代,项目越来越大,可执行文件占用的体积也是。这个议题就是介绍了滴滴是如何指定及实施一套工程优化的方案使得滴滴在不断迭代开发后还能保持苗条~

资源瘦身

删除无用图片

p5

滴滴自建了一个工具用来查找,并通过XCode匹配删除无用的图片,FengNiao:Link

大比例压缩

使用Google提供的Webp图片文件格式,优点包括:压缩率高,同时支持有损压缩和无损压缩;体积大幅减少,肉眼看不出差异;支持Alpha透明和24bit颜色数,相比而言PNG8色彩不够出现毛边;Gif转Animated Webp有损可减少64%,无损19%。相应的缺点就是:比PNG消耗2倍左右CPU和解码时间,全平台支持度不够。

一般而言,小于256色适合无损压缩,大于256的使用75%有损压缩

压缩工具iSparta:Link

WebP 项⽬目主⻚页:Link

iOS WebP 解析库:Link

大资源文件

下载后使用,比如表情包等

其它一些效果较小的方法

重复资源检测:Link

音频压缩瘦身:Link

简单图片用代码替换

将代码里的静态字符串抽取出来放到静态文件里

基于编译后的瘦身

LinkMap展现的是可执行文件的全貌,列出了编译后的每一个.o目标文件的信息。通过分析LinkMap的文件,我们可以了解各个独立模块的大小,进而分析那些模块可能是无用的,哪些模块体积过大等等。

基于编译过程的Clang Plugin瘦身

主要是分析调用关系,找出没被调用的代码:需要编写分析全部源码的插件,在编译过程中将插件作为Clang参数载入生成中间文件,然后编写工具分析所有的方法有哪些是会被调用的。

iOS APP分析无用代码(A source-code level/Clang Approach):Link

CLANG技术分享系列四:IOS APP无用代码/重复代码分析: Link

代码级瘦身

AppCode:类似于XCode的一款iOS/Mac开发工具,可以找出没有被使用的类、方法、值等等

结构瘦身

基于字符查找相似代码

SameCoderFinder Link 可以在源代码文件中检测到相同的function并显示两者之间的Hamming距离,这样就可以找到需要提取重复使用的相同代码,支持OC和Java

p43-46

对于大量代码比较如何提高效率:就是如何高效计算二进制序列中1的个数

空间换时间:比如8位的话列出1~256每个数中1的个数

基于代码结构查找相似代码

基于代码行的;基于标识符的;基于度量的;基于抽象语法树的;基于程序依赖图的等等

Q&A

1)第三方库

使用第三方库的源代码,再使用以上的方法进行瘦身,缺点就是需要自己维护,而我们就尽量维护一个稳定的版本

2)工作量和后续监控

基本每个事业部需要一到两个人做这项工作,后期的监控主要是实时监控文件的体积,一旦出现增量,就会提醒响应的人员

3)查找详细的方法

相似的功能通过组件化的实现,然后共享

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,264评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,549评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,389评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,616评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,461评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,351评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,776评论 3 387
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,414评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,722评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,760评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,537评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,381评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,787评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,030评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,304评论 1 252
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,734评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,943评论 2 336

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,517评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,142评论 25 707
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 11,952评论 4 60
  • 亲爱的家人,生命中所有的人事物,都是为你的灵魂成长,带来指引和协助的.他们的出现,都有自己的价值所在,如果...
    宋清澄阅读 1,188评论 0 0
  • 看到曹将的推文“每个人只能陪你走一段路”,自己想写写,“有个人能陪你走一辈子”。曹的角度是感激遇到、陪伴;我的角度...
    所以我开始美好阅读 296评论 0 1