难以置信(App性能优化)如何优化app性能,APP性能优化:卡顿、耗电、冷启动、安装包瘦身,

31次阅读
没有评论

APP的性能消耗主要由CPU和GPU

CPU(中央处理器)

对象的创建和销毁对象的属性调节布局计算文本的计算和排版图片的格式转换和解码图像的位图绘制

总之,负责所有的计算任务。

GPU(图形处理器)

纹理渲染/图像显示流程:

CPU把计算好的位图交给GPUGPU把位图渲染,并且放入帧缓存里然后视频控制器从缓存里读取这些渲染好的帧,显示到屏幕上。

iOS中是双缓冲机制,有前帧缓存,和后帧缓存

屏幕成像原理:

垂直同步信号(VSync)和 水平同步信号(HSync)分别在屏幕的垂直和水平方向上动态扫描

卡顿原理:

CPU和GPU超时,在垂直同步信号来临的时候没有处理好当前帧,画面会停留在上一帧,产生丢帧卡顿。

解决卡顿的主要思路:

尽可能减少CPU和GPU的资源消耗,避免超时。

60FPS的帧率,每隔16ms就会有一次VSync信号来临,所以CPU和GPU要在16ms内处理好当前帧。

CPU卡顿优化:

尽量使用轻量级的对象,尽量使用基本数据类型,在不涉及到时间处理的地方可以用CALayer取代UIView。不要去频繁的调整UIView的相关属性,比如说frame,bounds,transform等属性,尽量减少不急要的修改。尽量提前计算好布局,在有需要的时候一次性调整对应的属性,不要多次修改属性。Autolaout自动布局会比直接设置frame更加的消耗CPU资源。图片的size尽量最好更好跟UIImageView的size一致,避免CPU在额外的对图片进行伸缩处理。控制一下线程的最大并发量。尽量把耗时的操作放在字线程(文本处理计算,尺寸计算,绘制。图片处理,异步解码,异步绘制)。

GPU卡顿优化:

尽量减少视图的数量和层次,避免增加绘制和渲染的次数和时间。尽量避免短时间内大量图片的显示,尽量合成为一张图片进行显示。GPU能处理的最大纹理尺寸是4096*4096,一旦超过这个尺寸,就会占用CPU的资源进行处理,所以纹理尽量不要超过这个尺寸。减少透明的视图(alpha<1),不透明就设置opaque为YES。尽量避免出现离屏渲染。

在OPenGL 中 GPU有两种渲染方式:

On-Screen Rendering ( 当前屏幕渲染,在当前用于显示的屏幕缓冲区进行渲染操作)

Off-Screen Rendering(离屏渲染:在当前屏幕缓冲区以外重新开辟一个缓冲区进行渲染操作)

离屏渲染消耗性能的原因:

需要创建新的缓冲区。需要多次切换图形上下文环境,先是从当前屏幕切换到离屏,等到离屏渲染结束后,将离屏缓冲区的渲染结果显示到屏幕上,又需要将上下文环境从离屏切换到当前屏幕。

哪些操作会触发离屏渲染?

光栅化 ,layer.shouldRasterize = YES遮罩,layer.mask圆角,同时设置layer.masksToBounds = YES layer.cormerRadius大于0考虑通过CoreGraphics绘制裁剪圆角,或者叫美工切图阴影,layer.shadowXXX

如果设置了layer.shadowPath就不会产生离屏渲染

卡顿检测

可以添加Observer到主线程的RunLoop中,结束休眠到处理sorce0的时间,如果有连续n次的时间大于16ms,打印方法调用栈。

耗电优化

耗电的主要来源:

CPU功耗网络请求定位图像

优化项:

CPU功耗

尽可能降低CPU功耗,跟解决CPU卡顿是一个思路,如上文。少用定时器I/O操作{尽量不要频繁地写入小数据,最好一次性批量写入读写大量重要的数据时,可以考虑dispatch_io,其提供了基于CPU的异步操作文件I/O的API,用dispatch_io系统会优化磁盘的访问数据量较大时,建议使用数据库(SQLite,CoreData)

}

网络优化:

减少,压缩网络数据。如果多次请求的结果相同,尽量缓存。使用断点续传,否则网络不稳定的时候可能重复传输相同的内容,AFN自带此功能。网络不可用的时候,不要尝试网络连接,请求前现判断网络状态,一般的网络库(AFN)自带此功能。让用户可以取消长时间运行或者速度很慢的网络操作,设置合理的超时时间。批量传输,比如,下载视频流流的时候,不要传输很小的数据包,直接下载整个文件或者一大块一大块的文件,如果下载广告,一次性下载多个,然后再合适的时机和位置慢慢显示,如果下载电子邮件,一次下载多封,不要一封一封的下载。

定位优化

如果仅仅是想快速的获取用户的位置,最好用CLLocationManager的requestLocation方法。定位完成后,会自动让定位硬件断电。如果不是导航应用,尽量不要实时更新位置,定位完毕关闭定位服务。尽量降定位精度,尽量不要使用精度最高的KCLLocationAccuracyBest。需要后台定位,尽量设置pausesLocationUpdatesAutomatically为YES,如果用户不移动的时候,后台会暂停位置更新。尽量不要使用startMonitoringSignificantLocationChanges。

启动优化

APP的启动分为两种

冷启动(Cold Launch):从零开始启动APP热启动(Warn Launch):APP已经在内存中,在后台存活,从后太切换到前台

APP启动优化主要是针对冷启动

通过添加环境变量可以打印出APP的启动时间分析(Edit scheme -> Run -> Arguments)

DYLD_PRINT_STATISTICS设置为1

如果需要更详细的信息,那就将

DYLD_PRINT_STATISTICS_DETAIL设置为1

冷启动分为三大阶段:

dyld 加载动态库runtime 初始化类结构体main

dyld (dynamic link editor),apple的动态链接器,可以用来装载Mach-O文件(可执行文件,动态库文件等)

启动app时,dyld所做的事情:

装载APP的可执行文件,同时会递归加载所有依赖的动态库当dyld把所有可执行文件,动态库装载完毕之后,会通知runtime进行下一步的操作

启动app时,runtime所进行的操作:

调用map_images进行可执行文件内容的解析和处理在load_imagees中调用call_load_methods,调用所有class和category的+load方法进行各种objc结构体的初始化(注册objc类,初始化类对象等等)调用C++静态初始化器和_attribute_((constructor))修饰的函数

到此为止,可执行文件和动态库中所有的符号(class,protocol,Selector,IMP,。。。)都已经按照格式成功地加载到内存中,被runtime所管理

进入mian函数 ,UIAplicationMain AppDelegate 的回调方法,didfinishLaunch 等

APP启动按照不同的阶段进行优化

dyld

减少动态库,合并一些动态库(定期清理不必要的动态库)减少Objc类,分类的数量,减少Selector数量(定期清理不必要的类 分类)减少C++虚函数的使用Swift尽量使用struct

runtime

用+initialize方法和dispatch_once取代所有的_attribute_((construcror)),C++静态构造器,Objc的load.

main

在不影响用户体验的前提下,尽可能将一些操作延迟,不要全部都放在finishLaunching方法中按需加载

安装包瘦身

安装包(IPA),主要由可执行文件, 资源文件组成。

资源(图片,音频,视频等):

采取无损压缩去除没有用到的资源:https://github.com/tinymind/LSUnusedResources(一个可检测无用资源的开源项目)

可执行文件瘦身主要通过编译器的优化项:

Strip Linked Product,Make Strings Read-Only,symbols,Symbols Hidden by Default设置为YES。去掉异常支持,Enable C++ Exceptions,Enable Objectiv-C Exception 设置为NO,Other C Flag添加-info-exceptions。利用AppCode(一个收费的检车工具 https://www.jetbrains.com/objc/)检测未使用的代码:菜单栏->Code->inspect Code。编写LLVM插件检车出重复代码,未被使用的代码。生成linkMap文件,可以查看可执行文件的具体组成(build Settings->linking Write Link Map File 设置为YES ,Path to Link Map File 设置linkMap存储位置)。还可借助第三方工具解析LinkMap:https://github.com/huanxsd/LinkMap。

正文结束
 
669313929@qq.com
版权声明:本站原创文章,由 669313929@qq.com 2022-12-26发表,共计3603字。
转载说明:本文采摘于网络,不代表本站立场,转载联系作者并注明来源!
评论(没有评论)
载入中...