专栏首页正则ios性能优化
原创

ios性能优化

CPU(Central Processing Unit,中央处理器)

对象的创建和销毁、对象属性的调整、布局计算、文本的计算和排版、图片的格式转换和解码、图像的绘制(Core Graphics)都是通过 CPU 来做的。

GPU(Graphics Processing Unit,图形处理器)

纹理的渲染、

所要显示的信息一般是通过 CPU 计算或者解码,经过 CPU 的数据交给 GPU 渲染,渲染的工作在帧缓存的地方完成,然后从帧缓存读取数据到视频控制器上,最终显示在屏幕上。

在 iOS 中有双缓存机制,有前帧缓存、后帧缓存,这样渲染的效率很高。

屏幕成像原理

我们所看到的动态的屏幕的成像其实和视频一样也是一帧一帧组成的。为了把显示器的显示过程和系统的视频控制器进行同步,显示器(或者其他硬件)会用硬件时钟产生一系列的定时信号。当电子枪换到新的一行,准备进行扫描时,显示器会发出一个水平同步信号(Horizonal Synchronization),简称 HSync;而当一帧画面绘制完成后,电子枪回复到原位,准备画下一帧前,显示器会发出一个垂直同步信号(Vertical Synchronization),简称 VSync。显示器通常以固定频率进行刷新,这个刷新率就是 VSync 信号产生的频率。

卡顿现象

卡顿成因

前面我们知道,完成显示信息的过程是:CPU 计算数据 -> GPU 进行渲染 -> 屏幕发出 VSync 信号 -> 成像,假如屏幕已经发出了 VSync 但 GPU 还没有渲染完成,则只能将上一次的数据显示出来,以致于当前计算的帧数据丢失,这样就产生了卡顿,当前的帧数据计算好后只能等待下一个周期去渲染。

解决办法

解决卡顿现象的主要思路就是:尽可能减少 CPU 和 GPU 资源的消耗。

按照 60fps 的刷帧率,每隔 16ms 就会有一次 VSync 信号产生。那么针对 CPU 和 GPU 有以下优化方案:

CPU

  • 尽量用轻量级的对象 如:不用处理事件的 UI 控件可以考虑使用 CALayer;
  • 不要频繁地调用 UIView 的相关属性 如:frame、bounds、transform 等;
  • 尽量提前计算好布局,在有需要的时候一次性调整对应属性,不要多次修改;
  • Autolayout 会比直接设置 frame 消耗更多的 CPU 资源;
  • 图片的 size 和 UIImageView 的 size 保持一致;
  • 控制线程的最大并发数量;
  • 耗时操作放入子线程;如文本的尺寸计算、绘制,图片的解码、绘制等;

GPU

  • 尽量避免短时间内大量图片显示;
  • GPU 能处理的最大纹理尺寸是 4096 * 4096,超过这个尺寸就会占用 CPU 资源,所以纹理不能超过这个尺寸;
  • 尽量减少透视图的数量和层次;
  • 减少透明的视图(alpha < 1),不透明的就设置 opaque 为 YES;
  • 尽量避免离屏渲染;
离屏渲染

在 OpenGL 中,GPU 有两种渲染方式:

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

Off-Screen Rendering:离屏渲染,在当前屏幕缓冲区外开辟新的缓冲区进行渲染操作;

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

离屏渲染的整个过程,需要多次切换上下文环境,先是从当前屏幕(On-Screen)切换到离屏(Off-Screen),渲染结束后,将离屏缓冲区的渲染结果显示到屏幕上,上下文环境从离屏切换到当前屏幕,这个过程会造成性能的消耗。

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

  • 光栅化,layer.shouldRasterize = YES
  • 遮罩,layer.mask
  • 圆角,同时设置 layer.masksToBounds = YES,layer.cornerRadius > 0
    • 可以用 CoreGraphics 绘制裁剪圆角
  • 阴影
    • 如果设置了 layer.shadowPath 不会产生离屏渲染

卡顿检测

这里的卡顿检测主要是针对在主线程执行了耗时的操作所造成的,这样可以通过 RunLoop 来检测卡顿:添加 Observer 到主线程 RunLoop 中,通过监听 RunLoop 状态的切换的耗时,达到监控卡顿的目的。

耗电优化

耗电的主要来源为:

  • CPU 处理;
  • 网络请求;
  • 定位;
  • 图像渲染;

优化思路

  • 尽可能降低 CPU、GPU 功耗;
  • 少用定时器;
  • 优化 I/O 操作;
    • 尽量不要频繁写入小数据,最好一次性批量写入;
    • 读写大量重要数据时,可以用 dispatch_io,它提供了基于 GCD 的异步操作文件的 API,使用该 API 会优化磁盘访问;
    • 数据量大时,用数据库管理数据;
  • 网络优化;
    • 减少、压缩网络数据(JSON 比 XML 文件性能更高);
    • 若多次网络请求结果相同,尽量使用缓存;
    • 使用断点续传,否则网络不稳定时可能多次传输相同的内容;
    • 网络不可用时,不进行网络请求;
    • 让用户可以取消长时间运行或者速度很慢的网络操作,设置合适的超时时间;
    • 批量传输,如下载视频,不要传输很小的数据包,直接下载整个文件或者大块下载,然后慢慢展示;
  • 定位优化;
    • 如果只是需要快速确定用户位置,用 CLLocationManager 的 requestLocation 方法定位,定位完成后,定位硬件会自动断电;
    • 若不是导航应用,尽量不要实时更新位置,并为完毕就关掉定位服务;
    • 尽量降低定位精度,如不要使用精度最高的 KCLLocationAccuracyBest;
    • 需要后台定位时,尽量设置 pausesLocationUpdatesAutomatically 为 YES,若用户不怎么移动的时候,系统会自暂停位置更新;

启动优化

App 的启动分为两种:冷启动(Cold Launch) 和热启动(Warm Launch)。

前者表示从零开始启动 App,后者表示 App 已经存在内存中,在后台依然活着,再次点击图标启动 App。

App 启动的优化主要是针对冷启动的优化,通过添加环境变量可以打印出 App 的启动时间分析:Edit Scheme -> Run -> Arguments -> Environment Variables 添加 DYLD_PRINT_STATISTICS 设置为 1。

App 冷启动

冷启动可分为三个阶段:dyld 阶段、Runtime 阶段、main 阶段。

第一个阶段就是处理程序的镜像的阶段,第二个阶段是加载本程序的类、分类信息等等的 Runtime 阶段,最后是调用 main 函数阶段。

dyld

dyld(Dynamic Link Editor),Apple 的动态链接器,可以用来装载 Mach-O 文件(可执行文件、动态库等)。

启动 App 时,dyld 会装载 App 的可执行文件,同时会递归加载所有依赖的动态库,当 dyld 把可执行文件、动态库都装载完毕后,会通知 Runtime 进行做下一步的处理。

Runtime

启动 App 时,调用 map_images 进行可执行文件的内容解析和处理,再 load_images 中调用 call_load_methods 调用所有 Class 和 Category 的 load 方法,然后进行 objc 结构的初始化(注册类、初始化类对象等)。然后调用 C++ 静态初始化器和 __attribute_((constructor)) 修饰的函数,到此为止,可执行文件的和动态库中所有的符号(类、协议、方法等)都已经按照格式加载到内存中,被 Runtime 管理。

main

在 Runtime 阶段完成后,dyld 会调用 main 函数,接下来是 UIApplication 函数,AppDelegate 的 application: didFinishLaunchingWithOptions: 函数。

启动优化思路

针对不同的阶段,有不同的优化思路:

dyld

  • 减少动态库、合并动态库,定期清理不必要的动态库;
  • 减少类、分类的数量,减少 Selector 的数量,定期清理不必要的类、分类;
  • 减少 C++ 虚函数数量;
  • Swift 开发尽量使用 struct;

虚函数和 Java 中的抽象函数有点类似,但区别是,基类定义的虚函数,子类可以实现也可以不实现,而抽象函数子类一定要实现。

Runtime

  • 用 inilialize 方法和 dispatch_once 取代所有的 __attribute_((constructor))、C++ 静态构造器、以及 Objective-C 中的 load 方法;

main

  • 将一些耗时操作延迟执行,不要全部都放在 finishLaunching 方法中;

安装包瘦身

安装包(ipa)主要由可执行文件和资源文件组成,若不管理妥善则会造成安装包体积越来越大,所以针对资源优化我们可以将资源采取无损压缩,去除没用的资源。

对于可执行文件的瘦身,我们可以:

  • 从编译器层面优化
    • Strip Linked ProductMake Strings Read-OnlySymbols Hidden by Default 设置为 YES;
    • 去掉异常支持,Enable C++ ExceptionsEnable Objective-C Exceptions 设置为 NO,Other C Flags 添加 -fno-exceptions;
    • 利用 AppCode,检测未使用代码检测:菜单栏 -> Code -> Inspect Code;
    • 编写 LLVM 插件检测重复代码、未调用代码;
    • 通过生成 LinkMap 文件检测;

    LinkMap Build Setting -> LD_MAP_FILE_PATH: 设置文件路径Build Setting -> LD_GENERSTE_MAP_FILE -> YES

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • iOS 性能优化

    为了解释这个问题首先需要了解一下屏幕图像的显示原理。首先从 CRT 显示器原理说起,如下图所示。CRT 的电子枪从上到下逐行扫描,扫描完成后显示器就呈现一帧画面...

    赵哥窟
  • 深入剖析 iOS 性能优化

    在集合里数据量小的情况下时间复杂度对于性能的影响看起来微乎其微。但如果某个开发的功能是一个公共功能,无法预料调用者传入数据的量时,这个复杂度的优化显得非常重要了...

    用户7451029
  • <转>iOS性能优化:Instruments使用实战

    最近采用Instruments 来分析整个应用程序的性能.发现很多有意思的点,以及性能优化和一些分析性能消耗的技巧,小结如下。

    tandaxia
  • iOS 性能优化常用技巧总结import

    rectinajh
  • iOS性能优化——图片加载和处理

    本文基于WWDC2018-Image and Graphics Best Practices,对图片加载和处理的思考和总结。 本文不是WWDC翻译,如果需要了解...

    落影
  • iOS性能优化——图片加载和处理

    本文基于WWDC2018-Image and Graphics Best Practices,对图片加载和处理的思考和总结。 本文不是WWDC翻译,如果需要了...

    落影
  • iOS 性能优化 - TimeProfiler分析代码耗时

    注意:要在release模式(或者自定义的其他的打包模式)下分析,原因在release模式下:

    用户2932962
  • 【Dev Club分享】微信读书iOS性能优化

    “8小时内拼工作,8小时外拼成长”这是大家共同的理想。除了每天忙于工作外,我们都希望能更多地区吸收领域内的新知识与新技能,从而走向人生巅峰。 Dev Club ...

    腾讯Bugly
  • iOS性能优化系列篇之“列表流畅度优化”

    这一篇文章是iOS性能优化系列文章的的第二篇,主要内容是关于列表流畅度的优化。在具体内容的阐述过程中会结合性能优化的总体原则进行阐述,所以建议大家在阅读这篇文章...

    iOSSir
  • iOS性能优化xcode -> open developer tool - > Instuments 黄色基本和内存有关

    程序员不务正业
  • iOS 性能优化实践:头条抖音如何实现 OOM 崩溃率下降50%+

    OOM 其实是Out Of Memory的简称,指的是在 iOS 设备上当前应用因为内存占用过高而被操作系统强制终止,在用户侧的感知就是 App 一瞬间的闪退,...

    ios-lan
  • iOS App 启动性能优化

    导语 本文介绍了如何优化 iOS App 的启动性能,分为四个部分: 第一部分科普了一些和App启动性能相关的前置知识 第二部分主要讲如何定制启动性能的优化目标...

    腾讯Bugly
  • iOS开发之性能优化

    性能问题的主要原因是什么,原因有相同的,也有不同的,但归根到底,不外乎内存使用、代码效率、合适的策略逻辑、代码质量、安装包体积这一类问题。

    胖虎_callmeV
  • iOS最全性能优化之25个建议

    性能对 iOS 应用的开发尤其重要,如果你的应用失去反应或者很慢,失望的用户会在App Store写满差评。然而由于iOS设备的限制,有时搞好性能是一件难事。开...

    IT苦逼一枚
  • 深入浅出-iOS程序性能优化 (转载)

    iOS应用是非常注重用户体验的,不光是要求界面设计合理美观,也要求各种UI的反应灵敏,我相信大家对那种一拖就卡卡卡的 TableView 应用没什么好印象。

    tandaxia
  • 性能优化-MySQL性能优化参数

    对配置参数的说明: 配置参数的格式如下:(shell > mysqladmin -uroot -ppassword variables extended-st...

    cwl_java
  • 优化 iOS 程序性能的 25 个方法

    ARC(Automatic ReferenceCounting, 自动引用计数)和iOS5一起发布,它避免了最常见的也就是经常是由于我们忘记释放内存所造成的内存...

    哲洛不闹
  • iOS开发-视图渲染与性能优化

    前言 关于iOS的视图渲染流程,以及性能优化的建议。 源于WWDC视频。 我假设你是一个这样的开发者: 了解OpenGL ES; 了解view hierar...

    落影
  • 性能优化-Tomcat8优化

    tomcat服务器在JavaEE项目中使用率非常高,所以在生产环境对tomcat的优化也变得非常重要了。

    cwl_java

扫码关注云+社区

领取腾讯云代金券