iOS消息高并发优化

本篇文章并不打算过多的讲解技术实现的细节,大部分都是点到为止。我个人觉得技术细节虽然很重要,但是它只是实现一个功能的手段,更为重要的是实现功能的思路和方向。只有理清了思路,选定了方向,接下来的实现就应该是水到渠成了。

好了,下面我们该说说优化的事。我们看一下微信,基础功能就是聊天,能看到经常发生变化的就是消息列表,和聊天时候的聊天界面了,几乎只要你在使用它的时候这两个页面都会发生变化。所以针对性能上最重要的两个界面,一个是消息列表,一个是聊天界面。

一.消息列表页面的优化:

首先我们发消息时候观察一下消息列表的特性,当发送一条消息时候,消息的数量会变化,列表会出现在最上边的位置,列表内的内容会发生变化。从消息列表的特性,我们就可以分析出要优化的点了。通过这些点,我们做了一些优化:

1.如果列表消息从没显示过需要刷新列表,创建好一个cell后,将cell插入到第一位上,cell插入的性能要高于刷新tableview的性能。

2.如果消息已经显示过了,但是并不是第一位,则需要刷新列表。

3.如果消息已经显示,并且是第一位,则只需要cell的内容变化。

4.只修改cell里的内容,不进行刷新cell整体,这里要注意的是,一定要最小化刷新。刷新点越小,性能损耗越小。我们项目架构是MVVM,采用了ReactiveCocoa框架,针对每个cell上的可变化的控件数据进行了监听,每一个cell上对应一个vm,这样当vm上的数据变化时候,cell上的数据也就跟着变了。做到了最小化刷新。

5.避免使用autolayout计算位置,这个很重要,在性能要求高的情况下,autolayout计算会很耗时间,尤其在算tableview高度的时候可见一斑。可喜的是消息列表的高度是固定的,所以在计算高度时候我们并未花费时间。

6.使用(__kindof UITableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath而不使用-(nullable __kindof UITableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier来查找cell,因为下边的方法会多查一次,耗时更长一点。

7.cellForRowAtIndexPath方法只负责创建cell,willDisplayCell方法才给cell进行赋值操作。从方法名字就可以看出来原因

8.当来消息轰炸时候,必然会是不同的人发来的消息,会导致tableview不可避免的刷新,如果不加处理必然会卡顿,要知道,机器也是有瓶颈的。这里我们做的优化是根据cpu的使用率选择性的刷新tableview。后来我们发现微信也是有这个现象,并不是实时的刷新,我们猜测也是类似处理。

9.重绘制系统控件,相信你也发现了消息列表里,主要有两个控件,一个是头像,一个是label。而系统的UIImageView用来显示头像,未免有点重。我们的处理是使用UIView,设置View得layer.content来处理。针对layer层做的setImageWithUrl的第三方库也不少,大家可以自行查询。另一个就是label,如果你能集成UIView自己绘制一个label,我想也许会有一点效果。

以上我们对消息列表做的优化,写的并不全,只记得大概有这些吧。

二.聊天界面的优化:

聊天界面的优化算是比较繁琐的了,但是优化点跟回话列表的优化差不多。上边提到回话列表里最耗时的tableview的高度是固定的,而聊天界面的几乎每条消息的高度都可能不一样,所以我们在优化聊天界面时候最重要的一点就是计算tableviewcell的高度。而我们在计算tableview的高度是怎么做的呢?

其实这个网上千篇一律的优化tableview的方式是大同小异的。

主要有两个准则:

第一个是能在后台线程执行的都放在后台线程里。

第二个计算高度要放在显示之前。

上边提到我们使用的ReactiveCocoa基于事件流来处理消息,这个确实是为开发带来了很大的好处,处理层次非常清晰,开发效率的提升,代码复杂度降低,多人员开发分工分明,低耦合等这些好处充分让你感受到编程的乐趣,之后我们会出一篇关于架构的文章,这里只是稍提一嘴。当然即使你不用ReactiveCocoa也没关系,思路都是一样的。首先是你从底层异步接收到消息,进行消息的处理,包括数据库的处理,提供给View显示的对象处理,这里我们是用的VM层,其中也包括了消息的高度的计算,这些都是放在线程队列里,当所有的处理完成,然后进行主线程消息列表更新,进行插入一个cell和向上滚动一条消息的距离。我们之前把VM的创建放在了主线程,发现在32位机器上掉了10fps,这是让人不能忍受的事情。当然还有一点是尽量保证你的对象不要太大,如果太大也会影响性能,我们的vm就比较大,这也是以后性能上的隐患。优化tableView的另外一点就是cell的制作了,要说的跟上边第九条提到的也差不多,这里我也总结了一下几个原则:

1.巧妙的选择控件。比如上边提到的,如果只是显示一个图片,那么用View的layer.content性能自然是好一些。图片加点击也可以用view,然后监听view的touch事件,像button这种重量级的控件在性能为主的app面前,我对他们都是弃之如敝履。

2.减少使用layer层的cornerRadius,mask等圆角的绘制,这会引发离屏渲染,增加cpu的占用率。如果业务需要的话,我们可以通过UIBezierPath来drawInRect它。

3.避免设置透明

4.避免autolayout设定控件位置

5.尽可能的减少视图的层级,如果你能把所有的控件都绘制到一个View上,可想而知性能会爆棚。

三.其他优化

还有两大优化点不容忽视。

一是数据持久层的优化,就是所谓的数据库优化。

二就是内存优化。

关于持久层的优化严格来性能上通常不会有太大出入,只不过我们之前是直接针对底层sqlite数据库很简单的封装,后来用了fmdb,发现在插入性能上有了明显的提升。几乎用过的小伙伴都说好。持久化这边我们将fmdb,jsonModel进行封装了一个库,提供了友好的api,通常像这样使用[message findAll],[message save]等基本上都不需要写sql语句。回头我们会开源化。关于sql优化的我们总结了几点:

1.大批量插入时候,用事务可以几何倍的减少插入时间,原因是会把sql都加入内存,然后一次性提交。

2.针对经常变化的表、字段避免使用索引,当然索引带来的查询性能也是几何倍的增加,这里要说的一点是like并不会使用到索引

3.巧妙使用sql语句增删改查,能够用一条语句解决的事就不要使用两条,比如之前我们发现一个设置已读消息,是把这个人的消息取出来,然后再设置进去,后来我们直接进行了这个人的update语句,发现这块的处理性能高了很多。

4.当单条数据小于 20K 时,数据越小 SQLite 读取性能越高;单条数据大于 20K 时,直接写为文件速度会更快一些。

5.ibireme.com提到过在官网下载源码编译的sqlite性能会高几倍,我确实编译了一下,但是编译出来的是dylib,现在的系统是tbd,我没转过去,并且pods里依赖的也是tbd的,所以也就作罢了,主要放弃原因还是发现我们将很多数据库操作的部分去掉了,cpu占用率也没有发生变动。如果有搞定的同学记得分享一下。

数据库的大概能记住的也就这几点吧。

大最后说一嘴,多用Instuments来检测你的方法执行时间,以及CPU GPU占用率,这能够很好的帮你优化你的程序。

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

推荐阅读更多精彩内容

  • 概述在iOS开发中UITableView可以说是使用最广泛的控件,我们平时使用的软件中到处都可以看到它的影子,类似...
    liudhkk阅读 8,908评论 3 38
  • 工作了将近一个月的nusery里的团宠
    M_f7e0阅读 227评论 0 0
  • 今天参加老公同学的婚礼,突然想记录下这一刻,这时的心情,突然发现没有地方可以任我书写,
    小鱼爱喝酸奶阅读 324评论 0 0
  • 今天看了几集《今生是第一次》,觉得该记录点啥。故事的开始是女主在首尔打拼,到了30岁一事无成,没有房子没有爱情甚至...
    s沈小阅读 196评论 0 0
  • 水蕨(Ceratopteris thalictroides),水蕨科水蕨属的一种蕨,分布在热带和亚热带地区,我国湖...
    绿汀阅读 1,150评论 2 2