专栏名称: Cocoa开发者社区
CocoaChina苹果开发中文社区官方微信,提供教程资源、app推广营销、招聘、外包及培训信息、各类沙龙交流活动以及更多开发者服务。
目录
相关文章推荐
51好读  ›  专栏  ›  Cocoa开发者社区

iOS性能优化系列篇之“优化总体原则”

Cocoa开发者社区  · 公众号  · ios  · 2018-04-16 09:00

正文

笔者由于在iOS开发过程中做过一些优化的工作,对iOS性能优化有一些粗浅的认识,一直想把自己这些经验,简单总结一下。于是最近在工作闲暇时间,准备针对iOS开发的性能优化写一系列文章。


作为整个系列的第一篇,我打算针对iOS的优化中的一些总体原则做一些总结。因为我觉得无论列表流畅度优化也好、启动时间优化也好还是说其他方面的优化,都有一些共性的原则,只有掌握了这些总体性的原则,才能够更好的做优化,给我们具体的优化任务指明方向,让我们少绕弯路。后面如果时间允许,我可能会写一些关于列表流畅度、启动时间和内存优化等方面的文章。


在第一篇“优化总体原则”里面。我对优化总体原则总结出包括不要提前过度优化、要找到性能瓶颈、要在不同性能指标间权衡、要理解优化任务的底层运行机制和要有技术保障体系五大原则,其中具体阐述每一个原则的时候并不局限于性能优化方面,会发散到其他的相关领域,会对一些延伸的领域做一些简单的探讨,希望能够对读者有一些启示。以下是第一篇的主要内容。


一、不要提前过度优化


这个原则包括优化的过程中需要避免的两个陷阱,即提前优化和过度优化。


  • 提前优化指的是在开发的起始阶段就把性能优化作为一个重要的任务来考虑,在没有实际数据指标的基础上,为了性能提前做的些盲目优化工作。


    当然这个观点可能会引起争议,因为在某些开发领域,一些性能指标以历史的经验来说,的确有很大概率甚至必然会有性能瓶颈的问题,因此在架构初期就需要考虑性能的问题。 因此如果把“不要提前优化“这个观点推广所有开发领域上的话,我认为可能不一定合适。但是如果把此观点约束在iOS开发这一领域内,我个人认为还是成立的。因为在目前阶段iOS平台设备性能普遍较好,苹果无论是硬件层面还是系统层面对性能方面都做了大量的优化。所以我认为性能方面并不是iOS开发过程中需要首要考虑的因素。相比性能, 我个人认为在iOS开发的初始阶段,以下几个方面是更重要的,是需要首先考虑的。


    首先需要考虑的是架构的选择,这里的架构指的是Native架构、web架构、Native和web混合架构和跨平台的架构。这里面我个人的意见是首先应该尽量避免使用web架构,从Facebook早期的失败经验可以看出,web和Native相比的确存在诸多性能、体验等方面的问题。连大厂都无法彻底改善webview的问题,何况我们。但是在一些和用户体验相比,对动态化需求更加迫切的应用场景下,是可以选择web架构的,比如大家都一直在吐槽某铁路售票软件。Native架构的优势是产品体验好,对大多数iOS开发者技术栈友好,缺点是由于苹果对热更新做了严格限制,导致一些动态化的方案无法使用。Native和web混合架构主要是在Native架构上,在一些运营需求十分强烈的场景下(如电商等场景),某些模块使用web开发,这样既可以在App大部分场景下使用Native架构,保证用户体验,又满足了部分场景动态化的需求。跨平台的架构主要是可以减少多端开发的成本,使用一套代码完成iOS和Android两个平台的开发,目前主流的框架有ReactNative、Weex和Xamarin等。这些跨平台架构的愿景都很美好,但实际使用过程中,个人觉得现阶段并不比使用Native架构节省人力,其中会遇到许多已知的未知的坑,当然作为新的技术我们应该持开发的心态,但在使用时候也需要全面的评估,尤其作为一个可能有很长生命周期的应用,在使用非官方推荐的开发架构也好、开源库也好,如果后期无人维护的话,自己团队是不是有实力去接盘,如果不能,使用苹果官方推荐的技术栈则更稳妥些。


    其次需要考虑的是开发语言的选择,这个方面其实在选择了架构之后,也将可选的开发语言范围缩小到几个。而且实际项目开发中并不难选,因为团队开发人员的技术栈几乎决定了使用的开发语言,如果使用了大部分团队成员都不熟悉的语言,我相信即使所选语言在很多方面都有压倒性的优势,项目的推进也不会十分顺利。但是排除团队技术栈的因素,不同的开发语言的确是各有千秋。大家都知道iOS开发过程中,如果使用Native架构,官方的开发语言是objc和swift。objc是早期iOS开发的官方推荐语言,优点是其动态性,十分灵活,可以实现许多“黑魔法”,缺点语法略怪异(当然对于iOS开发者,使用久了也不觉得怪了),另外是对一些高级的语言特性支持的不是很好(记得最初使用objc开发iOS应用的时候,因为一些特殊的需求。由于objc不支持namespace,给团队造成了很大的困扰)。swift是苹果近年来主推的开发语言, 其吸收了许多其他语言的先进特性,也比较容易上手。关于两种开发语言的具体技术细节,大家有兴趣可以自己查看一些资料了解下。虽然苹果一直在力推swift,但是目前在国内iOS开发领域,由于一些用户基数大的主流App,均是在swift出现前使用objc编写的,而且大多经过了数年的版本迭代,加之早起swift ABI的不稳定和版本之间升级需要较多工作,还有swift和objc混编的一些问题,导致目前国内主流App大多仍使用objc作为开发语言。在一些创业公司,或者新的项目中,才有部分开发者使用swift,当然如果目光放长远的话,未来一定是swift的天下,这两年objc在每年的语言排名中逐年下降也侧面印证了这一点。 除了官方推荐的objc和是swift之外,如果使用跨平台等其他架构,还可以使用如js、c#等语言,有兴趣的可以自行了解下。


    再次需要考虑的是开发过程中具体的代码架构的选择,这里只简单谈谈Native架构下的代码架构选择。 目前iOS开发中常用的架构有MVC 、MVVM、VIPER、MVP等。关于这些架构,网上目前有很多的介绍,大家如果对具体细节有兴趣可以自行查阅。这里我只想补充一点,大家在学习和实践时,不要盲目跟风新技术,比如MVVM等架构未必比MVC好很多,MVC也未必是一个过时的框架。要知道很多新架构带来的扩展性和解耦行都是通过引入间接层来实现的,随之而来的可能是更多的胶水代码和更复杂的代码结构。希望大家在选择的时候能够根据项目的特点和团队自身的状况,选择最适合自己团队和项目的代码架构。


    除了上面说的三点,还有一些其他的关键点需要大家在项目初期考虑,比如如何在团队内部达成统一的代码风格?一些关键的技术如何选型?如何保证代码结构清晰、简单、扩展性好等等。性能问题可以在项目后期开始考虑,如果真的发现明显的性能问题再优化也来得及。比如项目一开始凭直觉感觉某一个模块可能会有性能问题,就盲目使用多线程,而不是根据实际情况具体问题具体分析。会导致程序复杂且容易出现线程安全问题。


  • 过度优化是指为了优化性能,过度增加系统复杂度和维护成本,使得开发周期变长。虽然可能性能上带来了一定的提升,但是和过度优化而导致的这些缺点来比,这么做显而易见是得不偿失的。


    笔者在工作过程中,发现许多同学在性能优化过程中,都容易陷入这种过度优化的陷阱。比如这一个简单的设置界面,一共只有十几个静态的cell, 如果去考虑圆角性能、离屏渲染、图片缓存、高度缓存、异步渲染甚至缓存布局信息,这些无疑是陷入了过度优化的陷阱,在这个应用背景下,简单快速的实现功能才是第一要务。在目前苹果的开发框架和平台上,一般如果出现性能问题,以我的实际经验来说,问题大部分是出在业务逻辑上面,所以遇到问题首先需要在业务逻辑上找问题,一些过度的极限的优化,完全是没有必要的。


    其实不光是性能优化,我发现许多同学在日常开发中,处处都有过度设计的情况。比如设计模式中的design happy这一陷阱,许多初学者在刚开始学习设计模式的时候,十分痴迷设计模式在解决不同问题时,对代码的解耦性和可扩展性上的威力,在开发过程中会时时刻刻想着应该用什么设计模式。结果导致很多的过度设计,其实我们写代码过程中,如果能遵守基本的SOLID原则,大部分情况下就可以写出高质量的代码。


    另外一个例子是组件化。近期iOS组件化是一个十分流行的话题,有许多团队提出了不同的组件化方案。实际项目中,团队在是否采用组件化方式开发的选择上,我希望要结合项目特点和团队组织架构形式具体问题具体分析,不要盲目跟风。在产品功能相对单一、开发人员较少、并行开发需求不强烈的情况下,推行组件化,不但增加系统复杂度,而且增加开发人员学习成本高,使得开发成本变大,我个人觉得这种规模的应用初期需要更多考虑的是如何快速上线、快速迭代和保证App质量。因此如果能够进行清晰的分层,严格遵守简单统一的架构模式即可。组件化比较适合从功能形态上可以清晰划分若干模块的产品,比如美团、58同城、淘宝和携程等产品,内部有多个业务模块,而且这些公司开发此类“航母”App的时候,会从组织架构把不同业务划分给不同的开发团队,为了能够保证不同团队之间能够独立并行开发和发版,最大程度上减少代码的依赖程度,这个时候应用组件化则是最佳实践。


    上面是对不要提前过度优化原则的详细阐述,并引申到相关开发领域,做了一些不成熟的探讨。下面介绍性能优化总体原则的第二个。


二、要找到性能瓶颈


在做优化前,一定要首先找到性能瓶颈有哪些,依性能严重程度逐个解决。不要盲目优化,否则最后可能花了很大的力气,优化掉的可能只是性能损耗很小的一部分。这一原则我觉得尤为重要,因为我在工作中遇见过包括我在内,很多不进行性能瓶颈查找,全凭主观猜测进行性能优化的情况。 在寻找性能瓶颈过程中,也需要注意以下问题。


  • 不要主观猜测,让性能评测数据说话。


    这一点十分重要,要时刻记住要以事实说话,不要以为某个函数使用的算法的时间复杂度是O(n2)就觉得一定会有性能问题,非要费很大力气优化到O(n*logn), 殊不知你的输入数据可能只有几十或者几百个,即使O(n2)也不会有多大的性能问题。也不要以为某个方法仅仅调用了系统库的一个简单get方法,就不会有什么性能问题,殊不知这个get方法里可能包含一些十分耗时的操作(比如磁盘IO)。因此在遇到性能问题的时候,一定不要凭主观猜测,实地跑一下性能数据,让数据告诉我们性能瓶颈究竟在哪里。


  • 要使用恰当的性能评测工具。


    对于开发版本的性能优化,Xcode提供的instruments绝对是最好的寻找性能瓶颈的工具,没有之一。instruments有丰富的性能评测工具,包括常用的Core Animation、Time Profiler、Leaks和Allocations等等。这些工具在分析函数执行时间、fps和内存等方面给我提供了十分便捷的功能。在使用instruments过程中需要注意:







请到「今天看啥」查看全文