一 代码的执行效率
在编程中,一段代码的执行效率时很难被估算和预测的,其主要受如下几个方面的影响:
算法依据的数据基础
编译器产生的代码质量和语言的执行效率
问题的输入规模
硬件的执行速度
在通常情况下,问题的输入规模和算法的数学基础是开发者需要考虑的因素。“时间复杂度”是用来描述算法执行效率的一个重要的标准。
时间频度:一个算法解决问题所消耗的时间。但是一般情况下,一个算法解决问题消耗的时间通常与输入值有关。
在计算一个算法的时间复杂度时,我们可以将算法分解为逐条语句,计算每条语句的时间频度后再进行累加,如下代码的作用是对输入求累加,我们通过注释来分析代码行时间复杂度:
sum=0; (1)
for(i=1;i<=n;i++) (n+1)
for(j=1;j<=n;j++) (n^2)
sum++; (n^2)
解:因为Θ(2n2+n+1)=n2(Θ即:去低阶项,去掉常数项,去掉高阶项的常参得到),所以T(n)=O(n2);
for (i=1;i<n;i++)
{
y=y+1; ①
for (j=0;j<=(2*n);j++)
x++; ②
}
解: 语句1的频度是n-1,语句2的频度是(n-1)*(2n+1)=2n2-n-1。f(n)=2n2-n-1+(n-1)=2n2-2;又Θ(2n2-2)=n2,该程序的时间复杂度T(n)=O(n2)。
一般情况下,对步进循环语句只需考虑循环体中语句的执行次数,忽略该语句中步长加1、终值判别、控制转移等成分,当有若干个循环语句时,算法的时间复杂度是由嵌套层数最多的循环语句中最内层语句的频度f(n)决定的。
算法的执行时间频度和n无关时,算法的时间复杂度为O(1),这时时间复杂度最小的函数,但是需要注意,时间复杂度小并不能说明算法执行耗费的时间短,比如对于一万行代码、每行只执行一次的情况,算法的复杂度也为O(1)。下图为常见的算法时间复杂度函数:
一些常用的算法复杂度和空间复杂度
分析一个算法的复杂度时,主要有三种情况可以考虑,最差情况(Worst Case)下的,平均情况(Average Case)的, 最好情况(Best Case)下的。
(以上时间复杂度的计算示例,参考了这位同学的资料,传送门)
在实际开发中,递归函数极容易产生时间复杂度为O(n!)的代码,多层嵌套的循环结构也会大大增加算法的时间复杂度。在编写程序时,要尽量将循环层数控制在3层以内,在使用递归函数时要格外小心。
二 内存占用
内存是一个应用程序运行的基础,在运行过程中,应用程序的代码、数据、资源等要加载进内存。保证稳定合理的内存占用量是开发者需要关注的重点之一。
ARC(自动引用计数)可以帮助开发者避免最常见的内存泄漏问题,但是其也不是万能的,循环引用CoreFoundation框架对象依然需要开发者手动处理。在实际开发中内存管理需要许多的细节技巧,例如对象的懒加载、列表Cell的重用、缓存数据的清理等。
使用Xcode调试工具可以看到项目运行时内存的使用情况。
三 CPU负担与能耗
在应用程序运行过程中,CPU占用率太高除了会使设备发热、耗电量增加之外,也极易造成崩溃。在Xcode开发工具中也可以检测CPU的占用率。
相信任何用户都不会喜欢使用一个耗电量极大的应用程序,过多的后台进程、大量的计算、大量的图像处理、定时器刷新和频繁定位等都会明显的增加应用程序的耗电量,在应用程序开发中,要多注意对这些方面的管理。
在Xcode的Energy Impact中可以查看当前应用程序运行的耗电量,如下图:
在ios中,可以使用如下代码获取电池电量与状态:
[UIDevice currentDevice].batteryLevel //获取电池电量
[UIDevice currentDevice].batteryState //获取电池状态
batteryLevel将返回一个1~0之间的浮点数,表示电池电量的百分比(在真机上才有效)。
batteryState用来获取电池的状态,下面是它的枚举:
四 动画的流畅度
动画流程程度也是应用程序的一个重要的性能指标。动画的流程程度主要取决于界面的刷新帧率。所谓帧率,就是屏幕每秒钟的刷新次数,ios系统大部分机型的极限帧率是60FPS,在ios中我们可以使用CADisplayLink去获取应用运行中的刷新帧率。
在ios开发中实现动画的方式有很多,应尽量减少通过循环的方式创建动画,以提高帧率,在动画实现过程中,对CALayer层的操作和对UIImage的缩放也会增加性能的压力,这些操作也应尽量避免。
五 网络缓存
网络请求我们可以从两个方面考虑进行优化:
从请求过程中寻求优化
从请求次数上寻求优化
关于“从请求过程中寻求优化”,首先需要借助抓包工具,观察哪一个请求耗时严重,时间消耗在了发送请求阶段还是等待回执阶段,之后可以通过优化接口设计,减少传输数据量,进行高效编码等方式来进行优化。
关于“从请求次数上寻求优化”,我们可以进行请求接口的合并,通过大量使用缓存技术来优化。基础的缓存技术如webView的缓存策略、图片数据的持久化缓存、单例数据中心的应用,都可以用来十分有效的提升请求性能。
再深入一步,我们可以分析用户的行为习惯,对于某些用户离开后很快回来概率很大的页面,进行数据的短时间缓存,减少不必要的请求。
六 应用程序启动时间
应用程序启动时间是重中之重,当启动时间超过3秒,大部分用户都会明显感觉到这几秒的等待,很可能没耐心再使用下去。
七 应用程序包尺寸
应用程序尺寸是一个重要的标准,对于同样可以满足需求的两个应用程序,当用户在AppStore中进行浏览时,一般会选择尺寸较小的那一个。
要对应用程序包尺寸进行优化,开发者可以采用下面几种方式:
清除冗余的资源,比如不用的图片素材,XIB文件和冗余的类文件。
对静态资源进行打包,在ios程序中,可能会使用到大量的静态JSON文件、HTML文件或文本文件。对这些文件进行压缩,在使用时代码进行解压可以有效的减小应用程序包尺寸。
进行Bitcode优化,在Xcode7以后,Apple提供了一项新的技术来支持对应用程序进行瘦身。对于开启了Bitcode优化的应用包,Apple会进行两次优化,针对不同机型输出不同的安装包,使用户下载的包尺寸得到显著减小。
********* <<IOS性能优化实战>>*********