前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 ><转>iOS性能优化:Instruments使用实战

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

作者头像
tandaxia
发布于 2018-09-27 04:26:30
发布于 2018-09-27 04:26:30
1.4K0
举报
文章被收录于专栏:谈补锅谈补锅

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

Instruments使用技巧

关于Instruments官方有一个很有用的用户使用Guide,当然如果不习惯官方英文可以在这里找到中文本翻译版本PDF参阅.Instruments 确实是一个很强大的工具,用它来收集关于一个或多个系统进程的性能和行为的数据极为方便,并能及时跟踪随着时间产生的数据.还可以广泛收集不同类型的数据.关于Instrument工具基本使用不在赘述.如下重点说明一些使用技巧.

1.概览

工具通过Xcode工具栏中Product->Profile可以启动,启动后界面如下:

Instrument概览[via by chenkai]

当点击Time Profiler应用程序开始运行后.就能获取到整个应用程序运行消耗时间分布和百分比.为了保证数据分析在统一使用场景真实行有如下点需要注意:

在开始进行应用程序性能分析的时候,一定要使用真机,模拟器运行在Mac上,然而Mac上的CPU往往比iOS设备要快。相反,Mac上的GPU和iOS设备的完全不一样,模拟器不得已要在软件层面(CPU)模拟设备的GPU,这意味着GPU相关的操作在模拟器上运行的更慢,尤其是使用CAEAGLLayer来写一些OpenGL的代码时候. 这就导致模拟器性能数据和用户真机使用性能数据相去甚运.

另外在开始性能分析前另外一件重要的事情是,应用程序运行一定要发布配置 而不是调试配置.

在发布环境打包的时候,编译器会引入一系列提高性能的优化,例如去掉调试符号或者移除并重新组织代码.另iOS引入一种"Watch Dog"[看门狗]机制.不同的场景下,“看门狗”会监测应用的性能。如果超出了该场景所规定的运行时间,“看门狗”就会强制终结这个应用的进程.开发者可以crashlog看到对应的日志.但Xcode在调试配置下会禁用"Watch Dog".

2.Time Profiler

选择Time Profiler启动.

time profile时间分析工具用来检测应用CPU的使用情况.可以看到应用程序中各个方法正在消耗CPU时间.使用大量CPU不一定是个问题.类似我们客户端中不同场景的天气动画[类似大雨]的路径就对CPU依赖就非常高,动画本身也是非常苛刻且耗费资源较多的任务.

点击Record 开始运行.

Time Profile 分析界面[via by chenkai]

刚开始我们拿到分析数据时往往是这样的:

性能数据[via by chenkai]

这里显示的是执行代码完整路径,其中系统和应用本身一些调用路径完全揉捏在一起.完全看不到我们关心的应用程序中实际代码执行耗时和代码路径实际所在位置.简单的方式可以快速勾选右边Call Tree中Separate Thread和Hide System Libraries两个选项[后面会解释选项作用]:

拆分后性能数据[via by chenkai]

可以看到直接能够看到应用程序各个方法调用耗时直接路径,剔除掉了系统相关方法和反向调用树路径.清爽很多.如果觉得这还不够直观,选择任意一个耗时方法分支[这里选择WeatherViewController viewDidLoad]双击进入会看到:

代码&耗时详情

可以直接定位到viewDidLoad的代码,也可以直观的看到改方法下调用其他方法耗时的时间.类似[self loadCityWeatherScroollerView]耗时是121x,x既耗时单位这里为ms毫秒.当然如果直接在Instrument找到问题觉得不方便修改,可以直接点击右上方Xcode按钮会直接定位Xcode对应调用方法入口.这样很容易能够快速定位代码占用CPU最多的方法.也可以打开Xcode快速修改并重新运行Profile来看修改后耗时前后对比.简单便捷.

这里对右侧call tree选项有必要做一下说明[官方user guide翻译]:

Separate By Thread:线程分离,只有这样才能在调用路径中能够清晰看到占用CPU最大的线程.

Invert Call Tree:从上到下跟踪堆栈信息.这个选项可以快捷的看到方法调用路径最深方法占用CPU耗时,比如FuncA{FunB{FunC}},勾选后堆栈以C->B->A把调用层级最深的C显示最外面. 

Hide Missing Symbols:如果dSYM无法找到你的APP或者调用系统框架的话,那么表中将看到调用方法名只能看到16进制的数值,勾选这个选项则可以隐藏这些符号,便于简化分析数据.

Hide System Libraries:这个就更有用了,勾选后耗时调用路径只会显示app耗时的代码,性能分析普遍我们都比较关系自己代码的耗时而不是系统的.基本是必选项.注意有些代码耗时也会纳入系统层级,可以进行勾选前后前后对执行路径进行比对会非常有用.

关于其他方法不再赘述.

性能分析&代码优化

我们这次性能优化主要针对如下两个使用场景:

A:应用程序第一次启动到进入天气首页的时间.

B:从后台切到前台天气首页占用时间.

在还没有拿到性能分析数据之前,一直认为第一次启动耗时主要浪费AppDelegate中第三方框架初始化上[类似WeiBo&WeChat 相关SDK初始化调用].当我们拿到实际性能数据耗时占用比时发现实际情况并非如此:

启动耗时

如上可以看到应用程序启动初始化工作主要会在MJAppDelegate如下两个方法展开:willFinishLaunchingWithOptions和didFinishLaunchingWithOptions,其中第三方框架初始化工作主要是willFinishLaunchingWithOptions中完成的.而实际情况耗时占比非常小.基本可以忽略不计.

而我们要优化两个启动时间场景,不同在于.第一次进入应用需要经过新手教程、添加城市、请求城市数据、解析数据、初始化天气首页UI元素并加载场景动画. 而从后台进入时则从本地存储DT文件中解析天气数据、初始化天气首页UI元素并加载天气动画.

1.NSDateFormatter问题凸显

针对这点重点分析应用启动&天气首页耗时. 在AB两个场景均发现加载首页元素发现如下问题:

NSDate(TimeAgo)getDateStrByTimeZone耗时

继续跟踪发现:

NSDate耗时

在AB两个场景里均出现加载MJLineChartView 和 TendencyChartView 时获取时区对应时间上耗时较大.而耗时主要在getDateStrByTimeZone这个方法调用上.

getDateStrByTimeZone方法

其中创建一个NSDateFormatter对象平均耗时33ms左右 而设置NSDateFormatter的3个属性平均耗时也在30ms左右.因为首页24小时天气和未来几天预报中.需要for循环中遍历数据,导致这个方法别重复调用多次,则消耗时间不断叠加.

针对这个问题:

NSDateFormatter对象本身初始化很慢,同样还有NSCalendar也是如此.然而在一些使用场景中不可避免要使用他们,比如Json数据解析中.使用这个对象同时避免其性能开销带来性能开销,一般比较好的方式是通过添加属性(推荐)或创建静态变量保持该对象只被初始化一次,而被多次复用.不得不值得一提的是设置一个NSDateFormatter属性速度差不多是和创建新的实例对象一样慢!

添加属性方式如下:

属性方式

针对NSDateFormatter时间开销出了重用对象外,尽量避免采用其处理多个日期格式.当然针对日期格式处理如果需要提高更多速度,可以直接采用C,可以采用第三方库来规避这个问题..

2.UIImage缓存取舍

在项目代码中看到大量使用如下代码:

UIImage使用

在Main Thread中发现不同动画场景中Image IO 开销和耗时所占比例均不一,在UIImage元素较多总体叠加耗时也会占用一定比例.内存开销也会明显增高.

UIImage加载图片方式一般有两种:

A:imagedNamed初始化

B:imageWithContentsOfFile初始化

二者不同之处在于,imageNamed默认加载图片成功后会内存中缓存图片,这个方法用一个指定的名字在系统缓存中查找并返回一个图片对象.如果缓存中没有找到相应的图片对象,则从指定地方加载图片然后缓存对象,并返回这个图片对象.

而imageWithContentsOfFile则仅只加载图片,不缓存.

大量使用imageNamed方式会在不需要缓存的地方额外增加开销CPU的时间来做这件事.当应用程序需要加载一张比较大的图片并且使用一次性,那么其实是没有必要去缓存这个图片的,用imageWithContentsOfFile是最为经济的方式,这样不会因为UIImage元素较多情况下,CPU会被逐个分散在不必要缓存上浪费过多时间.

使用场景需要编程时,应该根据实际应用场景加以区分,UIimage虽小,但使用元素较多问题会有所凸显.

3.天气首页加载策略

在AB两种场景把性能数据对比分析发现:

天气首页WeatherView更新耗时

天气首页WeatherView初始化耗时一直300ms-450ms之间,占据首页耗时很大一部分.且一直固定的开销.占据Main Thread3分之一.

而用户进入最先看到是天气首页上半部分:

上半部分

而下半部分需要滚动才能看到下半部分.且不一定触发:

下半部分

而现在整个首页View的初始化和更新全部放到主线程来做.其中WeatherInfoView updateAllInfo方法更新耗时最长.更多的view意味着更多的渲染,也就是意味更多的CPU和内存消耗,对于我们天气首页在UIScrollView里边嵌套了很多view更是如此。

而针对这种情况不要在主线程承载过多的操作.uikit渲染,用户输入回应都需要主进程上完成.主线程被意外block或者加载响应耗时过多都会影响到用户体验.而针对资源消耗过大操作,处理原则是最小化主线程的CPU占用,将工作“搬离”主线程, 不要阻塞主线程.类似本地一些IO完全移到其他线程来做.

调试time profiler过程中发现,即使占用了很少的CPU时间(如果你在Time Profiler中看到这些的数据),也可能会阻塞主线程。磁盘、网络、Lock、dispatch_sync以及向其它进程/线程发送消息都会阻塞主线 程。Time Profiler只能检测出占用CPU过多的堆栈,但检测不了这些IO的问题.很奇怪.在System Trace里面突然发现了CPU Time很低,但Wait Time很高的调用,说明在主线程处理I/O已经严重损害了app的性能,这个时候考虑把这个操作优化了.

而针对我们应用首页ui中多个view,在加载策略完全可以采用多线程进行同步加载,只把上半部分放在主线程中加载,下班可以同时开一个线程进行同步加载.这样可以大大降低组线程初始化和更新时间,当首页初始化完毕已经呈现是,下半部分其实已经另外一个线程处理完毕.

另外针对单个view 尽量不要在viewWillAppear费时的操作,viewWillAppear在 view 显示之前被调用,出于效率考虑,在这个方法中不要处理复杂费时的事情;只应该在这个方法设置 view 的显示属性之类的简单事情,比如背景色,字体等。不然,用户会明显感觉到 view 显示迟钝.

4:应用首次加载时间

应用首次启动加载操作:

首次加载

首次加载坐了如下操作:

A: 链接和载入:可以在Time Profile中显示dyld载入库函数,库会被映射到地址空间,同时完成绑定以及静态初始化.

B: UIKit初始化:如果应用的Root View Controller是由XIB实现的,也会在启动时被初始化.

C: 应用回调:调用UIApplicationDeleagte的回调:application:didFinishLaunchingWithOptions.

D: 第一次Core Animation调用:在启动后的方法-[UIApplication _resportAppLaunchFinished]中调用CA::Transaction::commit实现第一帧画面的绘制.

应用程序首次加载中启动方法willFinishLaunchingWithOptions和didFinishLaunchingWithOptions只做应用程序首次启动必须的要操作,而针对_dyid_start在初始化库framework函数的操作.不必要的Framework不要链接,避免首次加载耗时.

小结如上.很多地方代码调用和底层机制看的不是特别明白,整理总结关于优化部分实在有限,如上仅供各位参考.另外Instruments确实是把分析代码利器.目前没有任何一个第三方工具可以去替代.推荐各位使用. 作者:chenkai(简书

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2015-03-17 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
[1275]WSL的安装与使用
集成水平:WSL提供更深入的集成与主机操作系统Windows。例如,你可以在Windows的文件管理器中直接访问WSL文件系统,也可以在WSL中直接运行Windows的可执行文件。而虚拟机则创建了一个相对隔离的环境,虽然虚拟机可以访问主机文件系统,但需要特定的设置,并且整体上没有WSL那么直接和方便。
周小董
2024/04/07
5410
[1275]WSL的安装与使用
最详尽教程完整介绍-Windows 的 Linux 子系统-WSL1&WSL2
必须启用“适用于 Linux 的 Windows 子系统”可选功能并重启,然后才能在 Windows 上运行 Linux 发行版。
DevOps在路上
2023/05/16
7.3K0
最详尽教程完整介绍-Windows 的 Linux 子系统-WSL1&WSL2
WSL 2 的安装过程(以及介绍)
WSL全称为Windows Subsystem for Linux,官网译为:适用于 Linux 的 Windows 子系统 (WSL)
没有故事的陈师傅
2022/12/06
3.3K0
WSL 2 的安装过程(以及介绍)
Win 独享 WSL 并搭配 Oh My Zsh
适用于 Linux 的 Windows 子系统随 Windows 操作系统一起提供,但必须先启用它并安装 Linux 发行版,然后才能开始使用它。
acc8226
2022/05/17
3.5K0
WSL2:Windows 亲生的 Linux 子系统
在上一篇文章中,我们主要聊了一下:在 Windows 系统中,安装 WSL 子系统。
IOT物联网小镇
2021/08/13
3.4K1
WSL2:Windows 亲生的 Linux 子系统
重装操作系统经历之谈
重装win10纯净版操作系统 声明:①机器:笔记本联想电脑 ②本文仅是记录自己重装操作系统的经验,如果有错误,请指正! 第一步,准备一个官方渠道购买的优盘,不能少于8G,我自己重装的时候用的是16G的金士顿优盘。 第二步,请备份自己磁盘中的重要文件。切记!切记!切记! 第三步,在msdn官网下载iso文件镜像(这里可以根据自己的需求选择不同的版本,我本人选择的是纯净版的win10 ltsc 企业版2019)注意是下载到优盘 第四步:按照下面推荐的视频操作即可 推荐我在哔哩哔哩观看的一个视频https
WHYBIGDATA
2023/01/31
1.1K0
重装操作系统经历之谈
在Windows11上安装和使用WSL2
https://docs.microsoft.com/zh-cn/windows/wsl/
AiDBA宝典
2023/04/26
6.4K0
在Windows11上安装和使用WSL2
腾讯云服务器如何更换操作系统?
腾讯云服务器,提供了很多公共镜像,当时我们发现之前的操作系统不适合我们业务的时候,我们可以更换系统。我们后来要更换,应该怎么办呢?更换系统镜像就相当于重装系统了,腾讯云服务器更换系统支持这个操作的。
用户6558266
2019/10/26
30.1K0
腾讯云服务器如何更换操作系统?
Windows Server 2019开启WSL并安装子系统
命令执行可能需要几分钟,系统设置完成后会提示是否重启,我们输入“Y”重启系统以完成设置
jwj
2022/05/18
2.3K0
Win11使用WSL2安装Ubuntu22.04并启用GUI应用
Windows Subsystem for Linux (WSL) 允许在几分钟内在 Windows 机器上安装完整的 Ubuntu 终端环境,无需离开 Windows 即可开发跨平台应用程序。
zhangrelay
2022/05/10
42.4K0
Win11使用WSL2安装Ubuntu22.04并启用GUI应用
双系统系列:WSL2-更换Linux安装路径
上次我们说到在Windows下通过WSL2下载安装Linux系统,有一个大家经常会在Windows遇到的问题,那就是C盘容量不足。
小Bob来啦
2022/01/17
5K0
双系统系列:WSL2-更换Linux安装路径
win10使用WSL编译Linux C++项目
我们是做后台开发的,虽然我们的svr都泡在tlinux上,但是大部分同学写代码/看代码还都是在windows下。
breezeliu
2018/11/04
9.8K0
Windows 11安装WSL 2子系统与常见错误处理
最近我安装了Windows 11操作系统。作为一名开发者,Windows提供的WSL可以说是必不可少的工具。然而,安装WSL并没有一帆风顺。本文将记录安装方法以及遇到的一些错误。
七辰
2023/09/11
9.3K0
Windows 11安装WSL 2子系统与常见错误处理
在 Windows 下使用 WSL2 搭建 Kubernetes 集群
本文我们将介绍如何在 Windows10 下使用 WSL2 和 KinD 来搭建一套 Kubernetes 集群。在过去几年,Kubernetes 已经成为了容器编排领域事实上的标准。虽然现在已经有各种各样的 Kubernetes 发行版本和安装程序来部署 Kubernetes 环境了,除了云环境或者裸机环境下面之外,我们仍然需要在本地部署和运行 Kubernetes 集群,特别是对于相关的开发人员。
我是阳明
2020/06/15
15.6K2
在 Windows 下使用 WSL2 搭建 Kubernetes 集群
Win11的WSL2系统更换磁盘和wsl使用简介
版本    Windows 11 家庭中文版 版本    22H2 安装日期    ‎2022/‎7/‎29 操作系统版本    22621.232
zhangrelay
2022/08/10
4K0
Win11的WSL2系统更换磁盘和wsl使用简介
WSL:在 Windows 系统中开发 Linux 程序的又一神器
作为一名嵌入式软件开发工程师,在 Linux 系统下写代码、编译、调试是避免不了的事情。
IOT物联网小镇
2021/08/13
1.9K0
WSL:在 Windows 系统中开发 Linux 程序的又一神器
微软更新Linux子系统,编译WSL 2内核只需3步
今年,微软在Build大会上向开发者放了两个“大招”:Windows Terminal和WSL 2。两个工具都是为了向开发者提供类似于Linux的体验。
量子位
2019/07/17
1.8K0
微软更新Linux子系统,编译WSL 2内核只需3步
一键网络重装系统 – 魔改版(适用于Linux / Windows)
一键网络重装系统 – 魔改版,它可以通过Internet重新安装Linux和Windows以及常见的操作系统。例如:Linux(CentOS,Debian,Ubuntu、etc..),Windows(2019、2016、2012R2、2008R2、7、2003、etc..),以及其他系统(不断支持更多中)。
用户2135432
2023/10/21
1.3K0
Windows 系统中安装 WSL 子系统
在 Windows 命令行窗口,输入指令:wsl --list --verbose(或者输入简化版本:wsl -l -v),得到结果:
时代疯
2021/07/22
3.3K0
搭建自己的本地云平台,QIIME2图形界面玩转16S分析(WSL2+Docker+Galaxy qiime2)
之前分享过一个 qiime2 studio 图形界面的笔记(QIIME2图形界面版(Q2STUDIO)),是 qiime2 团队自己造的轮子,不过最近 qiime2 团队好像转向了利用 galaxy 轮子QIIME 2 2021.4 发布(qiime2 支持 galaxy 啦),还把官方的宣传和安装视频转载到过公众号,不过之前没有加字幕,看起来还是有点困难的,重新加了中英文字幕并校对了下。
用户1075469
2022/11/08
1.2K0
搭建自己的本地云平台,QIIME2图形界面玩转16S分析(WSL2+Docker+Galaxy qiime2)
推荐阅读
相关推荐
[1275]WSL的安装与使用
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档