iOS App的性能关注点
虽然iPhone的机能越来越好,但是app的功能也越来越复杂,性能从来都是移动开发的核心关注点之一。我们说一个app性能好,不是简单指感觉运行速度快,而应该是指应用启动快速、UI反馈响应及时、列表滚动操作流畅、内存使用合理,当然更不能随随便便Crash啦。工程师开发应用时除了在设计上要避免性能“坑”的出现,在实际遇到“坑”时也要能很快定位原因所在。定位性能问题原因当然不能靠猜,合理的方法是使用工具测量评估出投资回报最高的问题点,然后再加以优化。
本文会从以下几点介绍如何分析和优化iOS app的性能:启动时间、用户响应、内存、图形动画、文件和网络I/O。其中会用到Apple出品的性能分析神器“Instruments”。
启动时间
应用启动时间长短对用户第一次体验至关重要,同时系统对应用的启动、恢复等状态的运行时间也有严格的要求,在应用超时的情况下系统会直接关闭应用。以下是几个常见场景下系统对app运行时间的要求: * Launch 20秒 Resume 10秒 Suspend 10秒 Quit 6秒 Background Task 10分钟
要获取准确的app启动所需时间,最简单的方法时首先在main.c中添加如下代码:
1 2 3 |
|
然后在AppDelegate的回调方法application:didFinishLaunchingWithOptions
中添加:
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@”Lauched in %f seconds.”, (CFAbsoluteTimeGetCurrent() – StartTime));
});可能你会觉得为什么这样可拿到系统启动的时间,因为这个dispatch_async中提交的工作会在app主线程启动后的下一个run lopp中运行,此时app已经完成了载入并且将要显示第一帧画面,也就是系统会运行到`-[UIApplication _reportAppLaunchFinished]`之前。下图是用Instruments工具Time Profiler跑的调用栈,Instruments的使用方法建议看WWDC中与performance相关的[session录像](https://developer.apple.com/videos/wwdc),文字写起来太单薄不够直观哈。
从图中我们可以看到在系统调用[UIApplication _reportAppLaunchFinished]
之前完成了系统回调application:didFinishLaunchingWithOptions
。
App的启动会包括以下几个部分(来自WWDC 2012 Session 235):
1)链接和载入:可以在Time Profile中显示dyld载入库函数,库会被映射到地址空间,同时完成绑定以及静态初始化。
2)UIKit初始化:如果应用的Root View Controller是由XIB实现的,也会在启动时被初始化。
3)应用回调:调用UIApplicationDeleagte的回调:application:didFinishLaunchingWithOptions
4)第一次Core Animation调用:在启动后的方法-[UIApplication _resportAppLaunchFinished]
中调用CA::Transaction::commit
实现第一帧画面的绘制。如果你的程序启动很慢,能 做的首先是将与显示第一屏画面无关的操作放到之后执行;如果是用XIB文件load第一屏,XIB文件中的View层也要如果扁平,不要有太多图层。
用户响应
如何能够让用户觉得你的app响应迅速呢?当然是app用户所触发的操作都能得到立刻响应,即用户事件(User Event)能够被主线程的run loop及时处理。什么是run loop?可以想象成一个处理事件的select多路复用。主线程中的run loop当然主要是为了处理用户产生的事件啦,例如点击、滚动等。以后我们会详细聊聊run loop这个让人迷惑的东东。
要让主线程的run loop更好的响应用户事件,工程师应该尽量减少主线程干重活的时间,尤其是读文件啊,网络操作啊,大量运算啊这类重活,如果是阻塞操作,那就更是大忌了。我们可以用多线程(NSThread、NSOperationQueue, GCD,下一篇Blog就会聊到这多线程)将重活移出主线程,这属于显式并发。还有种隐式并发,例如view和layer的动画、layer的绘制以及PNG图片的解码都是在另一个子线程中执行的。除了使用多线程技术减轻主线程的负担外,减少主线程中阻塞也是提升用户体验的一个方法。使用Instruments中Time Profiler工具中的”Recod thread waiting”选项可以统计出app运行时各个线程中的阻塞系统调用情况,例如文件读写read/write,网络读写send/recv,加锁psynch_mutex_wait等。Instruments中的System Trace工具则能够记录所有的底层系统调用。
内存
内存问题从来都是iOS app的老大难问题,搞不好程序就爆了。由于iOS系统没有Swap文件(知道为啥不?留给悬念),在内存不足时会将只读数据(例如code page)从内存中移出,需要的时候再从disk上读如内存;可读写数据不会被系统从内存中移出,然而如果占用的内存达到一个阈值,系统会发出相应的通知和回调让应用release对象以回收内存,如果仍然不能减少内存使用量,系统会直接关闭应用。尤其是iOS 5.0之后,如果你的app收到了memory warning,那么脑袋也是和其他app一样放在了案板上,随时有可能被kill掉,并不是说一定会先Kill掉在后台的app。
App使用的内存除了我们在堆上分配的内存外(+[NSobject alloc]/malloc
),还会有更多使用内存的地方,比如代码和全局数据(TEXT和DATA),线程栈,图片,view 的layer backing store等等。因此处理内存问题,绝不仅仅是我们开发app时尽量少申请内存那么简单。
现在有了超炫的ARC,内存问题相对少了很多,开发效率也得到了提高。但是很多公司的项目仍然由于历史原因采用了手动管理内存,该做的活还是少不了。Xcode自带的静态分析功能可以帮你提前发现一些问题,然而有些内存问题是无法用静态分析来发现的,例如我们不断使用内存没有及时释放的问题,就无法使用静态分析器分析出来。此时可以使用Instruments的Allocations和Leaks工具来检查运行时的的内存使用以及泄露问题。
Allocations工具可以很直观的反应app的内存使用情况,还有个很赞“Mark Heap”功能,在上图左边下半部分中的Heapshot Analysis中。例如你在进入一个页面前点击一下“Mark Heap”,然后再退回上一页面点击一下“Mark Heap”,如果你在进出这个页面里所申请的内存都得到了合理的释放,那么堆的内存增长量就应该降至0(见上图右下部分)。
另一种严重的内存使用问题是引用了已经释放的内存,直接导致应用崩溃,而Allocation有一个选项Enable NSZombie detection能够在应用使用已经释放的内存时标注出来,同时显示错误发生的调用栈信息。这为解决问题提供了最直接的帮助,当然缺点是必须能够重现EXEC_BAD_ACCESS错误。
工具Leaks可以在应用运行时直接标示出存在内存泄露的代码,如果发生了内存泄露,可以从泄露详细信息中查看泄露的具体对象以及方法调用栈,大部分问题还是很好解决的。
图形和动画
图形性能对用户体验有直接的影响,Instruments中的Core Animation工具用于测量物理机上的图形性能,通过视图的刷新频率大小来判断应用的图形性能。例如一个复杂的列表滚动时它的刷新率应该努力趋近于60fps才能让用户觉得够流畅,从这个数字也可以算出run loop最长的响应时间应该是16毫秒。
启动Instruments的Core Animation工具后可以发现左下部分有一堆选项,我们来逐个介绍:
1) Color Blended Layers
Instruments可以在物理机上显示出被混合的图层Blended Layer(用红色标注),Blended Layer是因为这些Layer是透明的(Transparent),系统在渲染这些view时需要将该view和下层view混合(Blend)后才能计算出该像素点的实际颜色,如果这种blended layer很多,那么在滚动列表时就甭想有流畅的效果。
解决blended layer问题也很简单,检查红色区域view的opaque属性,记得设置成YES;检查backgroundColor属性是不是[UIColor clearColor]
,要知道背景颜色为clear color那可是图形性能的大敌,基本意味着blended layer是跑不了的了,为什么?自己思考一下:)
2) Color Hits Green and Misses Red
很多视图Layer由于Shadow、Mask和Gradient等原因渲染很高,因此UIKit提供了API用于缓存这些Layer:[layer setShouldRasterize:YES],系统会将这些Layer缓存成Bitmap位图供渲染使用,如果失效时便丢弃这些Bitmap重新生成。图层Rasterization栅格化好处是对刷新率影响较小,坏处是删格化处理后的Bitmap缓存需要占用内存,而且当图层需要缩放时,要对删格化后的Bitmap做额外计算。 使用这个选项后时,如果Rasterized的Layer失效,便会标注为红色,如果有效标注为绿色。当测试的应用频繁闪现出红色标注图层时,表明对图层做的Rasterization作用不大。
3) Color Misaligned Images
Misaligned Image表示要绘制的点无法直接映射到频幕上的像素点,此时系统需要对相邻的像素点做anti-aliasing反锯齿计算,增加了图形负担,通常这种问题出在对某些View的Frame重新计算和设置时产生的。
上图中被标注为黄色的图层,这是由于图层显示的是被缩放后的图片,如果这些图片是通过网络下载的,可以通过程序更新为确定的绘制大小来解决。还有些系统Navigation Bar和Tool Bar的背景图片使用的是拉伸(Streched)图片,也会被表示为黄色,这是属于正常情况,通常无需修改。这种问题一般对性能影响不大,而是可能会在边缘处虚化。
(4) Color Offscreen-Rendered Yellow
Offscreen-Rendering离屏渲染意思是iOS要显示一个视图时,需要先在后台用CPU计算出视图的Bitmap,再交给GPU做Onscreen-Rendering显示在屏幕上,因为显示一个视图需要两次计算,所以这种Offscreen-Rendering会导致app的图形性能下降。
大部分Offscreen-Rendering都是和视图Layer的Shadow和Mask相关,下列情况会导致视图的Offscreen-Rendering: 1. 使用Core Graphics (CG开头的类)。 2. 使用drawRect()方法,即使为空。 3. 将CALayer的属性shouldRasterize设置为YES。 4. 使用了CALayer的setMasksToBounds(masks)和setShadow*(shadow)方法。 5. 在屏幕上直接显示文字,包括Core Text。 6. 设置UIViewGroupOpacity。
这篇博文Designing for iOS: Graphics & Performance对offsreen以及图形性能有个很棒的介绍,(5) Color Copied Images Copied Image选项可以标注应用绘制时被Core Animation复制的图片,标注成蓝绿色。虽然我在运行时遇到过,不过个人感觉对图形性能影响不大。 (6) Color Immediately,Flash Updated Regions, Color OpenGL Fast Path Blue Color Immediately选项表示Instruments在做color-flush操作时取消10毫秒的延时。Flash Updated Regions选项用于用红色示标示出在屏幕上使用GPU计算绘制的图层。Color OpenGL Fast Path Blue选项用于用蓝色标示出在屏幕上由OpenGL compositor绘制的内容。 这三个选项对图形性能的分析意义较小,通常仅作为参考。
文件和网络I/O
如果需要对app的文件和网络I/O情况做分析,可以用到这三个Instruments工具System Usage、File Activity和Network。
工具System Usage可以统计出运行状态下应用的文件和网络IO操作数据。例如我们发现应用启动后又一个峰值,这可能存在问题,我们可以利用System Usage工具的详细信息栏查看应用是由于对哪些文件的读写操作导致了峰值。
工具File Activity只能在模拟器中运行,因此数据采集可能不是非常准确。它同样可以详细给出读取的文件属性、大小、载入时间等信息,适合与System Usage配合使用。
Network工具则可以采集到应用的TCP/IP和UDP的使用信息(传输的数据量、当前所有TCP连接等),用得不多,做网络使用状况分析时用用还行。
更多阅读
涉及iOS App性能的知识很多,上面只是冰山一角,重点推荐WWDC的session。
WWDC 2012:
- 406: Adopting Automatic Reference Counting
- 238: iOS App Performance: Graphics and Animations
- 242: iOS App Performance: Memory
- 235: iOS App Performance: Responsiveness
- 409: Learning Instruments
- 706: Networking Best Practices
- 514: OpenGL ES Tools and Techniques
- 506: Optimizing 2D Graphics and Animation Performance
- 601: Optimizing Web Content in UIWebViews and Websites on iOS
- 225: Up and Running: Making a Great Impression with Every Launch
WWDC 2011:
- 105: Polishing Your App: Tips and tricks to improve the responsiveness and performance
- 121: Understanding UIKit Rendering
- 131 performance optimization on iphone os
- 308: Blocks and Grand Central Dispatch in Practice
- 323: Introducing Automatic Reference Counting
- 312: iOS Performance and Power Optimization with Instruments
还有几篇不错的blog:
http://oleb.net/blog/2011/11/ios5-tech-talk-michael-jurewitz-on-performance-measurement/
http://eng.pulse.me/tips-for-improving-performance-of-your-ios-application/
http://robots.thoughtbot.com/post/36591648724/designing-for-ios-graphics-performance
http://www.touchwonders.com/en/how-to-make-your-apps-feel-responsive-and-fast-part-2/
相关推荐
本文介绍了如何优化iOSApp的启动性能。本文分为四个部分:第一部分科普了一些和App启动性能相关的前置知识第二部分主要讲如何定制启动性能的优化目标第三部分通过在WiFi管家这个具体项目的优化过程,分享一些有用的...
映客直播iOS-App-性能优化.pdf
在iOS应用开发中,性能优化是提升用户体验的重要环节。随着应用功能的不断增加,对性能的要求也在不断提高。以下是一些提高iOS应用性能的建议和技巧。 ### 基础级别的性能提升建议: 1. **使用ARC(Automatic ...
在iOS和macOS平台上进行性能优化是开发过程中至关重要的一环,它关系到应用程序的响应速度、用户体验以及设备电池寿命。本资源"iOS and macOS 性能优化"提供了一个详细指南,帮助开发者提升应用的效率。以下是一些...
iOS-Performance-Optimization:iOS 性能优化专题合集.zip,关于iOS 性能优化梳理、内存泄露、卡顿、网络、GPU、电量、 App 包体积瘦身、启动速度优化等、Instruments 高级技巧、常见的优化技能- Get — Edit
8. 性能优化:考虑到用户体验,应用需要进行性能优化,如减少内存占用,优化网络请求,使用懒加载策略等。 以上就是关于“iOS APP开发 微博 Xcode”这一主题的主要知识点。在实际开发中,开发者需要结合设计原则、...
本文主要讨论了手淘iOS性能优化的探索,涵盖了性能度量、启动器设计、App启动器研发架构、数据卡口优化、性能监控等多个方面。 首先,作者提出了性能面临的问题,包括页面加载缓慢、启动不达标、版本质量下降等问题...
iOS APP的启动速度优化是提升用户体验的关键因素,尤其是在竞争激烈的移动应用市场中。启动速度不仅影响用户的第一印象,还可能直接影响用户的留存率。本文将详细分析App启动过程中的各个环节,并提出相应的优化策略...
- **性能优化**:提供了关于内存管理、运行时性能调优等方面的实用技巧,帮助开发者提升应用程序的整体性能。 - **错误处理**:讨论了Swift 5中的错误处理机制,包括如何优雅地处理错误情况,以及如何利用Swift的...
在iOS应用开发中,夜间模式是一项重要的功能,它允许用户...以上就是关于“iOSApp夜间模式”和RNThemeManager的相关知识点。通过熟练掌握这些内容,开发者可以轻松地在React Native应用中实现夜间模式,提升用户体验。
它涵盖了多个关键知识点,包括设计模式、组件化、依赖注入、测试策略以及性能优化等。 在iOS应用开发中,良好的架构是成功的关键。书中首先会介绍常见的设计模式,如MVC(模型-视图-控制器)、MVVM(模型-视图-视图...
移动App性能评测与优化是移动应用开发中的关键环节,它涉及到用户体验、系统资源消耗、电池寿命等多个方面。本文将深入探讨这一主题,旨在提供全面的知识点解析。 首先,我们需要理解性能评测的重要性。移动设备...
iOS 应用在运行状态上的差异直接影响其行为和性能。当应用处于前台时,它可以充分利用系统资源进行高效的用户交互;而在后台时,则受到严格的资源限制。理解这两种状态下的行为差异有助于开发者优化应用,确保无论在...
总的来说,iOS App的测试流程涵盖了功能测试、中断测试、安装卸载测试、性能测试等多个方面,既要考虑软件的基本功能,也要关注手机特性的适配和优化。测试人员需要了解这些特定的测试方法和技术,以确保App在复杂...
本文将基于"swift-iOS性能优化总结"的主题,详细探讨内存管理、UI流畅性、网络请求、GPU优化、电量消耗控制、App包体积减小、启动速度提升以及Instruments工具的高级使用技巧等方面的知识点。 首先,我们来关注内存...
在iOS应用开发中,性能优化是不可或缺的一环。当用户遇到响应缓慢或卡顿的应用时,他们可能会在App Store留下负面评价,因此,确保应用的流畅运行至关重要。由于iOS设备的硬件限制,优化工作并不简单,而且在开发...
在iOS应用开发中,"启动app时的广告页"是一个常见的设计策略,旨在吸引用户注意力,展示品牌信息或推广特定内容。...通过合理的布局、动画设计以及性能优化,可以创建一个既有效传达信息又不损害用户体验的启动广告页。