iOS之性能优化面试题五

115 阅读4分钟

这是我参与11月更文挑战的第25天,活动详情查看:2021最后一次更文挑战

如何优化 APP 的电量?

程序的耗电主要在以下四个方面:

  • CPU处理
  • 定位
  • 网络
  • 图像

优化的途径主要体现在以下几个方面:

  • 尽可能降低 CPU、GPU 的功耗。

  • 尽量少用 定时器。

  • 优化 I/O 操作。 - 不要频繁写入小数据,而是积攒到一定数量再写入
    - 读写大量的数据可以使用 Dispatch_io ,GCD 内部已经做了优化。  - 数据量比较大时,建议使用数据库

  • 网络方面的优化

    • 减少压缩网络数据 (XML -> JSON -> ProtoBuf),如果可能建议使用 ProtoBuf。
    • 如果请求的返回数据相同,可以使用 NSCache 进行缓存
    • 使用断点续传,避免因网络失败后要重新下载。
    • 网络不可用的时候,不尝试进行网络请求
    • 长时间的网络请求,要提供可以取消的操作
    • 采取批量传输。下载视频流的时候,尽量一大块一大块的进行下载,广告可以一次下载多个
  • 定位层面的优化 -如果只是需要快速确定用户位置,最好用 CLLocationManager 的 requestLocation 方 法。定位完成后,会自动让定位硬件断电

    • 如果不是导航应用,尽量不要实时更新位置,定位完毕就关掉定位服务\
    • 尽量降低定位精度,比如尽量不要使用精度最高的 kCLLocationAccuracyBest\
    • 需要后台定位时,尽量设置 pausesLocationUpdatesAutomatically 为 YES,如果用户不太可能移动的时候系统会自动暂停位置更新
    • 尽 量 不 要 使 用 startMonitoringSignificantLocationChanges ,优先考虑startMonitoringForRegion:
  • 硬件检测优化

    • 用户移动、摇晃、倾斜设备时,会产生动作(motion)事件,这些事件由加速度计、陀螺仪、磁力计等硬件检测。在不需要检测的场合,应该及时关闭这些硬件

如何有效降低 APP 包的大小? 

降低包大小需要从两方面着手

可执行文件

  • 编译器优化
    • Strip Linked Product、Make Strings Read-Only、Symbols Hidden by Default 设置为 YES
    • 去掉异常支持,Enable C++ Exceptions、Enable Objective-C Exceptions 设置为 NO, Other C Flags 添加 -fno-exceptions
    • 利用 AppCode 检测未使用的代码:菜单栏 -> Code -> Inspect Code
    • 编写LLVM插件检测出重复代码、未被调用的代码

资源

资源包括 图片、音频、视频 等

  • 优化的方式可以对资源进行无损的压缩
  • 去除没有用到的资源

什么是 离屏渲染?什么情况下会触发?该如何应对? 

离屏渲染就是在当前屏幕缓冲区以外,新开辟一个缓冲区进行操作。

离屏渲染出发的场景有以下:

  • 圆角 (maskToBounds 并用才会触发)
  • 图层蒙版
  • 阴影
  • 光栅化

为什么要避免离屏渲染?

CPU、GPU 在绘制渲染视图时做了大量的工作。离屏渲染发生在 GPU 层面上,会创建新的渲染缓冲区,会触发 OpenGL 的多通道渲染管线,图形上下文的切换会造成额外的开销,增加 GPU 工作量。如果 CPU GPU 累计耗时 16.67 毫秒还没有完成,就会造成卡顿掉帧。

圆角属性、蒙层遮罩 都会触发离屏渲染。指定了以上属性,标记了它在新的图形上下文中,在未愈合之前,不可以用于显示的时候就出发了离屏渲染。

  • 在OpenGL中,GPU有2种渲染方式

    • On-ScreenRendering:当前屏幕渲染,在当前用于显示的屏幕缓冲区进行渲染操作
    • Off-ScreenRendering:离屏渲染,在当前屏幕缓冲区以外新开辟一个缓冲区进行渲染操作
  • 离屏渲染消耗性能的原因

    • 需要创建新的缓冲区
    • 离屏渲染的整个过程,需要多次切换上下文环境,先是从当前屏幕(On-Screen)切换到离屏 (Off-Screen);等到离屏渲染结束以后,将离屏缓冲区的渲染结果显示到屏幕上,又需要将上下文 环境从离屏切换到当前屏幕
  • 哪些操作会触发离屏渲染?

    • 光栅化,layer.shouldRasterize=YES
    • 遮罩,layer.mask
    • 圆角,同时设置 layer.masksToBounds = YES、layer.cornerRadius 大于0
    • 考虑通过 CoreGraphics 绘制裁剪圆角,或者叫美工提供圆角图片
    • 阴影,layer.shadowXXX,如果设置了 layer.shadowPath 就不会产生离屏渲染