这是我前面几天碰到的面试题:
如何对定位和分析项目中影响性能的地方? 以及如何进行性能优化?
我的答案:
定位方法:
instruments
在 iOS 上进行性能分析的时候, 首先考虑借助 instruments 这个利器分析出问题出在哪, 不要凭空想象, 不然你可能把精力花在了 1% 的问题上, 最后发现其实啥都没优化, 比如要查看程序哪些部分最耗时, 可以使用 Time Profiler, 要查看内存是否泄漏了, 可以使用 Leaks 等. 关于 instruments 网上有很多资料, 作为一个合格 iOS 开发者, 熟悉这个工具还是很有必要的.
作为一个开发者, 有一个学习的氛围跟一个交流圈子特别重要, 这是一个我的 iOS 交流群: 638302184, 不管你是小白还是大牛欢迎入驻 , 分享 BAT, 阿里面试题, 面试经验, 讨论技术, 大家一起交流学习成长! 希望帮助开发者少走弯路.
优化建议:
1. 用 ARC 管理内存
* ARC(Automatic Reference Counting, 自动引用计数)和 iOS5 一起发布, 它避免了最常见的也就是经常是由于我们忘记释放内存所造成的内存泄露. 它自动为你管理 retain 和 release 的过程, 所以你就不必去手动干预了. 下面是你会经常用来去创建一个 View 的代码段: UIView *view = [[UIView alloc] init];
- * // ...
- * [self.view addSubview:view];
- * [view release];
* 忘掉代码段结尾的 release 简直像记得吃饭一样简单. 而 ARC 会自动在底层为你做这些工作. 除了帮你避免内存泄露, ARC 还可以帮你提高性能, 它能保证释放掉不再需要的对象的内存. 这都啥年代了, 你应该在你的所有项目里使用 ARC!
2. 在正确的地方使用 reuseIdentifier
* 一个开发中常见的错误就是没有给 UITableViewCells, UICollectionViewCells, 甚至是 UITableViewHeaderFooterViews 设置正确的 reuseIdentifier.
* 为了性能最优化, table view 用 tableView:cellForRowAtIndexPath: 为 rows 分配 cells 的时候, 它的数据应该重用自 UITableViewCell. 一个 table view 维持一个队列的数据可重用的 UITableViewCell 对象. 不使用 reuseIdentifier 的话, 每显示一行 table view 就不得不设置全新的 cell. 这对性能的影响可是相当大的, 尤其会使 App 的滚动体验大打折扣.
* 自 iOS6 起, 除了 UICollectionView 的 cells 和补充 views, 你也应该在 header 和 footer views 中使用 reuseIdentifiers
3. 尽量把 views 设置为完全不透明
* 如果你有透明的 Views 你应该设置它们的 opaque(不透明)属性为 YES. 例如一个黑色半透明的可以设置为一个灰色不透明的 View 替代. 原因是这会使系统用一个最优的方式渲染这些 views. 这个简单的属性在 IB 或者代码里都可以设定.
* Apple 的文档对于为图片设置透明属性的描述是:
* (opaque)这个属性给渲染系统提供了一个如何处理这个 view 的提示. 如果设为 YES, 渲染系统就认为这个 view 是完全不透明的, 这使得渲染系统优化一些渲染过程和提高性能. 如果设置为 NO, 渲染系统正常地和其它内容组成这个 View. 默认值是 YES.
* 在相对比较静止的画面中, 设置这个属性不会有太大影响. 然而当这个 view 嵌在 scroll view 里边, 或者是一个复杂动画的一部分, 不设置这个属性的话会在很大程度上影响 App 的性能.
* 换种说法, 大家可能更好理解: 只要一个视图的不透明度小于 1, 就会导致 blending.blending 操作在 iOS 的图形处理器 (GPU) 中完成的, blending 主要指的是混合像素颜色的计算. 举个例子, 我们把两个图层叠加在一起, 如果第一个图层的有透明效果, 则最终像素的颜色计算需要将第二个图层也考虑进来. 这一过程即为 Blending. 为什么 Blending 会导致性能的损失? 原因是很直观的, 如果一个图层是完全不透明的, 则系统直接显示该图层的颜色即可. 而如果图层是带透明效果的, 则会引入更多的计算, 因为需要把下面的图层也包括进来, 进行混合后颜色的计算.
4. 避免过于庞大的 XIB
* iOS5 中加入的 Storyboards(分镜)正在快速取代 XIB. 然而 XIB 在一些场景中仍然很有用. 比如你的 App 需要适应 iOS5 之前的设备, 或者你有一个自定义的可重用的 view, 你就不可避免地要用到他们.
* 如果你不得不 XIB 的话, 使他们尽量简单. 尝试为每个 Controller 配置一个单独的 XIB, 尽可能把一个 View Controller 的 view 层次结构分散到单独的 XIB 中去.
* 需要注意的是, 当你加载一个 XIB 的时候所有内容都被放在了内存里, 包括任何图片. 如果有一个不会即刻用到的 view, 你这就是在浪费宝贵的内存资源了. Storyboards 就是另一码事儿了, storyboard 仅在需要时实例化一个 view controller.
* 当你加载一个引用了图片或者声音资源的 nib 时, nib 加载代码会把图片和声音文件写进内存. 在 OS X 中, 图片和声音资源被缓存在 named cache 中以便将来用到时获取. 在 iOS 中, 仅图片资源会被存进 named caches. 取决于你所在的平台, 使用 NSImage 或 UIImage 的 imageNamed: 方法来获取图片资源.
5. 不要阻塞主线程
* 永远不要使主线程承担过多. 因为 UIKit 在主线程上做所有工作, 渲染, 管理触摸反应, 回应输入等都需要在它上面完成. 一直使用主线程的风险就是如果你的代码真的 block 了主线程, 你的 App 会失去反应
* 大部分阻碍主进程的情形是你的 App 在做一些牵涉到读写外部资源的 I/O 操作, 比如存储或者网络. 或者使用像 AFNetworking 这样的框架来异步地做这些操作. 如果你需要做其它类型的需要耗费巨大资源的操作 (比如时间敏感的计算或者存储读写) 那就用 Grand Central Dispatch, 或者 NSOperation 和 NSOperationQueues. 你可以使用 NSURLConnection 异步地做网络操作: + (void)sendAsynchronousRequest:(NSURLRequest *)request queue:(NSOperationQueue *)queue completionHandler:(void (^)(NSURLResponse*, NSData*, NSError*))handler
6. 在 Image Views 中调整图片大小
* 如果要在 UIImageView 中显示一个来自 bundle 的图片, 你应保证图片的大小和 UIImageView 的大小相同. 在运行中缩放图片是很耗费资源的, 特别是 UIImageView 嵌套在 UIScrollView 中的情况下.
* 如果图片是从远端服务加载的你不能控制图片大小, 比如在下载前调整到合适大小的话, 你可以在下载完成后, 最好是用 background thread, 缩放一次, 然后在 UIImageView 中使用缩放后的图片.
7. 选择正确的 Collection
学会选择对业务场景最合适的类或者对象是写出能效高的代码的基础. 当处理 collections 时这句话尤其正确.
Apple 有一个 Collections Programming Topics 的文档详尽介绍了可用的 classes 间的差别和你该在哪些场景中使用它们. 这对于任何使用 collections 的人来说是一个必读的文档.
呵呵, 我就知道你因为太长没看... 这是一些常见 collection 的总结:
* Arrays: 有序的一组值. 使用 index 来 lookup 很快, 使用 value lookup 很慢, 插入 / 删除很慢.
* Dictionaries: 存储键值对. 用键来查找比较快.
* Sets: 无序的一组值. 用值来查找很快, 插入 / 删除很快.
8. 打开 gzip 压缩
* 大量 App 依赖于远端资源和第三方 API, 你可能会开发一个需要从远端下载 xml, JSON, html 或者其它格式的 App.
* 问题是我们的目标是移动设备, 因此你就不能指望网络状况有多好. 一个用户现在还在 edge 网络, 下一分钟可能就切换到了 3G. 不论什么场景, 你肯定不想让你的用户等太长时间.
* 减小文档的一个方式就是在服务端和你的 App 中打开 gzip. 这对于文字这种能有更高压缩率的数据来说会有更显著的效用. 好消息是, iOS 已经在 NSURLConnection 中默认支持了 gzip 压缩, 当然 AFNetworking 这些基于它的框架亦然. 像 Google App Engine 这些云服务提供者也已经支持了压缩输出.
来源: https://www.cnblogs.com/Mcci7/p/10739293.html