使用Instruments工具深入分析iOS应用性能与启动时间优化

使用Instruments工具优化iOS应用的性能与启动时间

01使用Instruments分析应用性能

△ Instruments工具概述

最近,我尝试使用 Instruments 来深入分析我的iOS应用程序的性能。这一工具揭示了许多有趣的发现,同时也提供了一些关于性能优化和性能数据收集的宝贵技巧。在此,我将这些经验总结如下。

Instruments是一个灵活且强大的工具,它不仅功能强大,而且极为灵活。Instruments能够轻松地收集一个或多个系统进程的性能和行为数据,并能实时跟踪数据随时间的变化。此外,它还能广泛收集各种类型的数据,为开发者提供了丰富的分析手段。关于Instruments的基本使用方法,这里不再赘述,我们将重点关注一些高级使用技巧。

对于iOS开发,除了Instruments,开发者也可以考虑使用KeyMob 这样的综合工具进行性能监控和优化。KeyMob专为iOS开发设计,提供性能监控、文件管理、日志分析等功能,能够实时监控CPU、GPU、内存、FPS等指标,帮助开发者更全面地分析应用性能并优化启动时间。

1.1 △ Time Profiler使用技巧

启动Time Profiler后,你可以获取到iOS应用程序运行时的详细时间分布和百分比。然而,为了确保数据分析的准确性,在真实的使用场景下进行,有几个关键点需要注意。首先,进行性能分析时应使用真机而非模拟器,因为Mac上的CPU速度往往快于iOS设备。但需要注意的是,Mac上的GPU与iOS设备完全不同,模拟器需要在软件层面模拟设备的GPU,这可能导致GPU相关操作在模拟器上运行缓慢,特别是在使用CAEAGLLayer编写OpenGL代码时。因此,模拟器的性能数据可能与真实设备上的性能数据存在显著差异。

此外,在开始性能分析之前,确保应用程序以发布配置而非调试配置运行。发布配置中,编译器会引入一系列性能优化措施,如去除调试符号、重构代码等。同时,iOS还引入了"Watch Dog"机制来监测应用的性能。如果应用在特定场景下超出规定的运行时间,"Watch Dog"将强制终止应用进程,并生成crashlog供开发者查看。但在调试配置下,"Watch Dog"功能会被禁用。

Time Profiler可以帮助分析应用的CPU使用情况。启动Time Profiler后,你可以利用时间分析工具来检测应用程序的CPU使用情况。这个工具会展示出应用程序中各个方法正在消耗的CPU时间,帮助你了解哪些部分可能存在性能问题。需要注意的是,即使某些部分使用了大量的CPU,这并不总是问题所在。例如,在我们的应用程序中,不同场景下的天气动画,特别是大雨动画,对CPU的依赖度很高,因为动画本身是一种非常苛刻且资源密集型的任务。

在开始分析前,点击Record按钮开始运行你的应用程序

Time Profiler的分析界面 中,我们首先观察到的是执行代码的完整路径。需要注意的是,系统和应用本身的某些调用路径可能交织在一起,这使得我们难以清晰地看到我们真正关心的应用程序中实际代码的执行耗时和代码路径的实际位置。为了更清晰地展示这些信息,我们可以简单地勾选界面右侧的Call Tree中的Separate Thread和Hide System Libraries两个选项。这样,我们就能更专注于应用程序本身的性能数据,从而更好地进行问题分析。

ebp)

在经过拆分处理后,我们可以更直观地看到应用程序中各个方法调用的直接路径和耗时情况,系统相关方法和反向调用树路径已被有效剔除,界面显得更加清爽。若仍觉得不够直观,不妨尝试双击任意一个耗时方法分支,例如选择"WeatherViewController viewDidLoad"进行深入分析,届时将能看到更详细的性能数据。

△ 优化应用启动与性能

接下来,让我们了解一下右侧的 call tree 选项:

  • Separate By Thread: 勾选此项后,可以在调用路径中更清晰地看到占用CPU最多的线程。

  • Invert Call Tree: 此选项允许我们从上到下跟踪堆栈信息,从而快速查看方法调用路径中最深的方法及其CPU耗时。

  • Hide Missing Symbols: 如果dSYM无法找到你的APP或系统框架,那么在表中只会看到16进制的数值。勾选此项可以隐藏这些符号,简化分析数据。

  • Hide System Libraries: 勾选后,性能分析将只显示应用程序自身的代码耗时,隐藏系统库的调用路径。这对于我们关注自己代码的耗时情况非常有用。

在优化 应用启动与性能 时,我们需要关注以下两个使用场景:

A. 应用程序从启动到进入天气首页的时间。

B. 从后台切换到前台天气首页的时间。

在获取到性能分析数据之前,我们往往误以为应用程序首次启动的耗时主要归因于AppDelegate中第三方框架的初始化,例如WeiBo和WeChat相关SDK的初始化调用。然而,当我们仔细分析实际的性能数据耗时占用比时,却发现情况并非完全如此。

深入分析应用启动及天气首页的耗时 过程中,我们发现了一个共同的问题:在AB两个不同的启动场景中,加载首页元素时都遇到了NSDateFormatter相关的问题。继续深入追踪,我们发现了一个共同的问题:在加载首页元素时,无论是AB两个启动场景中的哪一个,都遇到了NSDateFormatter相关的耗时问题,具体表现为NSDate(TimeAgo)getDateStrByTimeZone方法的执行时间过长。

AB两个不同的启动场景中,我们均观察到在加载MJLineChartView和TendencyChartView时,获取时区对应的时间会耗费相对较长的时间。这种耗时问题主要集中在getDateStrByTimeZone方法的调用上

优化NSDateFormatter对象的使用 可以简化分析数据,并通过添加属性来实现这一优化策略。通过分析,我们会发现,创建NSDateFormatter对象所需平均时间约为33毫秒,而设置其三个属性则平均耗费约30毫秒。为了解决这种性能问题,可以通过以下方式优化:

  1. 重用对象来减少NSDateFormatter的时间开销

  2. 尽量避免使用NSDateFormatter处理多个不同的日期格式

  3. 使用C语言或引入第三方库提高日期格式处理的效率

此外,在分析UIImage的 加载方式 时,我们发现不同动画场景中Image IO的开销和耗时存在差异。随着UIImage元素的增多,总体叠加耗时也会相应增加,同时内存开销也会明显上升。因此,在编程时需要根据实际应用场景来选择合适的UIImage加载方式。

通过对比分析AB两种场景下的性能数据,我们发现天气首页的 WeatherView组件在更新时 存在显著的耗时问题。其初始化过程持续在300ms至450ms之间,占据了整个页面加载过程中相当大的比例。这一固定开销对主线程造成了不小的负担,影响了用户体验。

为了 改善用户体验,我们采用多线程同步加载的方式。具体来说,就是将上半部分内容留在主线程加载,而下半部分则同时开启一个线程进行同步加载。这种方式能有效缩短主线程的初始化和更新时间。此外,避免在viewWillAppear方法中执行耗时操作,因为这会让用户感知到view显示时的延迟。

通过优化NSDateFormatter对象的使用和UIImage的加载方式等策略,可以显著 改善应用的启动时间和整体性能,提升用户体验。

相关推荐
zbmwa2 小时前
jetpack compose 副作用 snapshotFlow
android
爱笑鱼2 小时前
Binder 实战(九):一次调用变慢,到底卡在客户端、驱动、Binder 线程还是 Handler?
android
2601_960906722 小时前
AI研发加速中式及泛亚洲
人工智能·vscode·macos·sublime text·phpstorm
sg_knight2 小时前
Codex CLI 安装全攻略:macOS / Linux / Windows(WSL2)三端实战
linux·windows·macos·openai·ai编程·coding·codex
恋猫de小郭3 小时前
Flutter hit,一个可以灵活控制溢出点击的第三方包
android·前端·flutter
古韵3 小时前
小程序上传进度条,还要自己监听 onProgressUpdate 吗?
前端·javascript·uni-app
我命由我123453 小时前
Kotlin 面向对象 - 枚举排序
android·java·开发语言·java-ee·kotlin·android studio·android-studio
程序喵大人3 小时前
【C++进阶】STL容器与迭代器 - 10 把容器、迭代器和数据流串成一个小程序
开发语言·c++·容器·小程序·迭代器·stl
90后的晨仔4 小时前
Xcode 26.6编译 AFNetworking 报错全解:5 种方案从应急到根治
ios