iOS性能分析和优化

      前言: 随着项目的扩大和功能的增多,代码没有经过严格的调试和优化,要么任性地卡顿运行,要么就低调地崩溃,最后导致用户用着不开心,开发者也比较烦恼。

  为了突破这个这个关卡其实并不难,首先开发者只要在Xcode自带的监控调试工具 Instruments 上花点功夫就能够让代码顺畅运行。Instruments 提供了很多检测功能,重点介绍一下我常用的几大类:

    Analyze—静态分析

    Leaks—内存泄露(动态内存泄露检测)

   Allocations:监测内存使用 / 分配情况  

   Time Profiler:检测分析代码的执行时间。

 (一)第一波基本概念

1.1.内存空间的划分: 我们知道,一个进程占用的内存空间,包含5种不同的数据区:(1)BSS段:通常是存放未初始化的全局变量;(2)数据段:通常是存放已初始化的全局变量。(3)代码段:通常是存放程序执行代码。(4)堆:通常是用于存放进程运行中被动态分配的内存段 , OC对象(所有继承自NSObject的对象)就存放在堆里。(5)栈:由编译器自动分配释放,存放函数的参数值,局部变量等值。

栈内存是系统来管理的,因此我们常说的内存管理,指的是堆内存的管理,也就是所有OC对象的创建和销毁的管理。伴随着iOS5的到来,苹果推出了ARC(自动引用计数)技术,此模式下编译器会自动在合适的地方插入retain、release、autorelease语句,也就是说编译器会自动生成内存管理的代码,解放了广大程序猿的双手,也基本上避免了内存泄露问题,但是呢...

1.2.内存泄露: 百度百科给的定义是:"内存泄漏也称作'存储渗漏',用动态存储分配函数动态开辟的空间,在使用完毕后未释放,结果导致一直占据该内存单元。直到程序结束。(其实说白了就是该内存空间使用完毕之后未回收)即所谓内存泄漏"。在iOS应用中的内存泄露,原因一般有循环引用、错用Strong/copy等。

(二)第二波( Instruments多功能检测)

2.1. Analyze—静态分析

顾名思义,静态分析不需要运行程序,就能检查到存在内存泄露的地方。

1. 使用方法:打开Xcode,command + shift + B;或者Xcode - Product - Analyze;

2. 常见的三种泄露情形:

(1)创建了一个对象,但是并没有使用。Xcode提示信息: Value Stored to 'number' is never read 。翻译一下:存储在'number'里的值从未被读取过。

(2)创建了一个(指针可变的)对象,且初始化了,但是初始化的值一直没读取过。Xcode提示信息: Value Stored to 'str' during its initialization is never read

(3)调用了让某个对象引用计数加1的函数,但没有调用相应让其引用计数减1的函数。Xcode提示信息: Potential leak of an object stored into 'subImageRef' 。 翻译一下:subImageRef对象的内存单元有潜在的泄露风险。



2.2: Leaks—内存泄露

Leaks是动态的内存泄露检查工具,需要一边运行程序,一边检测。

1.使用方法: 进入Xcode,command + control + i ;或者Xcode - Xcode - Open Developer Tool - Instruments; 或者Xcode - Product - Profile。选择Leaks。

一般用静态分析检查过的代码,内存泄露都比较少。测试了有3个项目能点的按钮都点了,能进的页面都进的,Leaks也没检测到泄露。

2.3. Allocations—内存分配

Allocations是检测程序运行过程中的内存分配情况的,也需要同时运行着程序。

1.打开方法:同上。

2.界面情况如下:

2.4:Time Profiler 主要作用:分析代码的执行时间,以便找出导致程序变慢的原因。

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

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

另外在开始性能分析前,另外一件很重要的事情是,应用程序一定要运行在Distribution 而不是Debug模式下.

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

如图所示


相关配置项如下

Separate by Thread: 每个线程应该分开考虑。只有这样你才能揪出那些大量占用CPU的"重"线程

Invert Call Tree: 从上倒下跟踪堆栈,这意味着你看到的表中的方法,将已从第0帧开始取样,这通常你是想要的,只有这样你才能看到CPU中话费时间最深的方法.也就是说FuncA{FunB{FunC}} 勾选此项后堆栈以C->B-A 把调用层级最深的C显示在最外面

Hide Missing Symbols: 如果dSYM无法找到你的app或者系统框架的话,那么表中看不到方法名只能看到十六进制的数值,如果勾线此项可以隐藏这些符号,便于简化数据

Hide System Libraries: 勾选此项你会显示你app的代码,这是非常有用的. 因为通常你只关心cpu花在自己代码上的时间不是系统上的

Show Obj-C Only: 只显示oc代码 ,如果你的程序是像OpenGl这样的程序,不要勾选侧向因为他有可能是C++的

Flatten Recursion: 递归函数, 每个堆栈跟踪一个条目

Top Functions: 一个函数花费的时间直接在该函数中的总和,以及在函数调用该函数所花费的时间的总时间。

因此,如果函数A调用B,那么A的时间报告在A花费的时间加上B.花费的时间,这非常有用,因为它可以让你每次下到调用堆栈时挑最大的时间数字,归零在你最耗时的方法。如上做了相关配置之后会显示如下图所示情形


(三)第三波(小结)

除了以上所描述常用instruments外,下面一些偶尔也会用到

Core Data:监测读取、缓存未命中、保存等操作,能直观显示是否保存次数远超实际需要。

Cocoa Layout:观察约束变化,找出布局代码的问题所在。 Network:跟踪 TCP / IP 和 UDP / IP 连接。

Automations:创建和编辑测试脚本来自动化 iOS 应用的用户界面测试。


   最后instruments只是一组工具,帮助我们分析代码的工具,可能检查的出的内存问题和性能问题,肯定还是由代码造成的。问题的本质还是养成良好的代码习惯,才是根本的解决方法。

     首先是避免出现静态分析里提到的三种常见内存泄露问题,测试的好几个项目里,都有出现类似的问题。在此有以下几点tips:

  tip1:哪些情况会增加App的内存占用?(开发中未完成的项目)

   (1) 创建对象,定义变量。

 (2)调用一个函数或方法。 

tip2:哪些情况会增加CPU的消耗?(bireme)

     (1) 创建对象、调整对象属性、销毁对象。

  (2)布局计算和Autolayout。

  ( 3)文本的计算和渲染。

  ( 4)图片的解码和绘制。 (用Time Profiler分析一下,可以更直观地感受到哪些操作比较耗时,使用方法同上。)

  tip3:

    做好cell等可复用对象的重用;可以只创建一次的对象,不要创建多次(比如页面的某个功能弹窗); 用较少的对象和方法调用去实现功能;将耗时的操作放在子线程等可以对内存和性能做一些优化 。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容

  • 前言: 随着项目的扩大和功能的增多,代码没有经过严格的调试和优化,要么任性地卡顿运行,要么就低调地崩溃,最后导致用...
    闲云清烟阅读 2,449评论 0 0
  • 先来一发苹果官网上Instruments User Guide,其实没啥用,英语不好的也懒得去看。(反正我是看不懂...
    和珏猫阅读 29,864评论 51 376
  • *面试心声:其实这些题本人都没怎么背,但是在上海 两周半 面了大约10家 收到差不多3个offer,总结起来就是把...
    Dove_iOS阅读 27,134评论 30 470
  • xcode instrument测试工具使用 [http://www.jianshu.com/p/92cd90e6...
    清风沐沐阅读 5,815评论 4 17
  • 生活中,其实没有真正的喜欢,都是欲望作祟之后的邪念,然后通过时间和相处酝酿出来的孤独的药,也就是一见钟情...
    城南十里阅读 619评论 0 2