成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

iOS objc_msgSend尾調用優化機制

開發 開發工具 前端
本文基于Objective-C對象的消息傳遞機制,詳細分析OC對 objc_msgSend 的尾調用優化方式。

本文基于Objective-C對象的消息傳遞機制,詳細分析OC對 objc_msgSend 的尾調用優化方式。

1. 什么是尾調用?

尾調用( TailCall):某個函數的***一步僅僅只是調用了一個函數(可以是自身,可以是另一個函數)。 QiShare提醒:注意 “僅僅” 兩個字。

尾調用例子:

  1. // 尾調用:  
  2. - (NSInteger)funcA:(NSInteger)num {       
  3. /*  Some codes... */       
  4. if(num == 0) {        return [self funcA:num];// 尾調用->自身    }           
  5. if (num > 0) {        return [self funcB:num];// 尾調用->函數funcB    }           
  6. return [self funcC:num];// 尾調用->函數funcC}  

正例解釋:funcA 的***一步僅僅調用了另一個函數。不論是調用funcA、funcB還是funcC 都屬于尾調用。(不論調用函數的位置在哪,只要***一步僅僅調用一個函數就行。)

反例:不是尾調用的例子

  1. // 不是尾調用1:  
  2. - (NSInteger)funcA:(NSInteger)num {       
  3. NSInteger num = [self funcB:(num)];       
  4. return num;// 不是尾調用->***一步是返回一個值,而不是調用一個函數  
  5. }  

反例解釋:不是尾調用。因為***一步是返回一個值,而不是僅僅調用一個函數。

  1. // 不是尾調用2: 
  2. - (NSInteger)funcA:(NSInteger)num {     
  3. return [self funcB:(num)] + 1;// 不是尾調用->原因:末尾有+1操作} 

反例解釋:不是尾調用。因為***一步不僅調用了函數還有 +1 操作。

2. OC的尾調用優化體現在哪里?

小編準備了一個Demo:通過“斷點”和“當前內存情況”查看有無尾調用優化。

場景一:無優化(因為追加了.0,不屬于尾調用)

無優化Demo效果圖:

這種場景下,每次函數調用一直在進棧,不斷申請棧空間,***會棧溢出,最終導致崩潰。 空間復雜度O(n),時間復雜度O(n)。

圖解如下:

場景二:有尾調用優化

優化Demo效果圖:

這種場景下,每次函數調用一直在重用棧幀,不申請棧空間。空間復雜度O(1),時間復雜度O(n)。

圖解如下:

3. OC是如何實現尾調用優化的?

這次討論起因于《Effective Objective-C 2.0》的原文:

如果某函數的***一項操作是調用另外一個函數,那么就可以運用 “尾調用優化”技術。編譯器會生成調轉至另一函數所需的指令碼,而且不會向調用堆棧中推入新的 “棧幀”(frame stack)。只有當某函數的***一個操作僅僅是調用其他函數而 不會將其返回值另作他用時,才能執行 “尾調用優化”。

這項優化對 objc_msgSend非常關鍵,如果不這么做的話,那么每次調用Objective-C方法之前,都需要為調用objc_msgSend函數準備“棧幀”,大家在“棧蹤跡”(stack trace)中可以看到這種“棧幀”。此外,如果不優化,還會過早地發生“棧溢出”(stack overflow)現象。

作者對尾調用的描述十分精簡。在這里,QiShare團隊對這段話進行了詳細的分析:

(1)尾調用優化的本質:很簡單,就是棧幀的復用。

(2)尾調用優化的條件有三點:

  • 尾調用函數不需要訪問當前棧幀中的變量。(變量可以作為形參,但是不能作為實參)
  • 尾調用返回后,函數沒有語句需要執行。(***一步僅僅只能執行一個函數)
  • 尾調用結果就是函數的返回值。(不能有別的“附加品”,***一步僅僅只能是執行一個函數)

(3)函數調用的過程:函數調用會在內存中申請一塊“棧幀”,保存調用的地址和內部變量等信息。如果函數A內部調用函數B,那么在函數A的棧幀上就會加上一個函數B的棧幀。如果函數B再調用了函數C,那么函數A的棧幀上就會有序加上函數B和函數C的棧幀。如果C運行結束了,返回到函數B,C的棧幀才會消失。

(4)尾調用優化實現原理:當函數A的***一步僅僅是調用另一個函數B時(或者調用自身函數A),這時,因為函數A的位置信息和內部變量已經不會再用到了,直接把函數A的棧幀交給函數B使用。

尾調用優化關鍵圖解:

總結:

  • 尾調用:某個函數的***一步僅僅調用了一個函數(可以是自身,可以是另一個函數)。
  • OC的尾調用優化的本質是:棧幀的復用
  • 尾調用優化實現原理:當函數A的***一步僅僅是調用另一個函數B時(或者調用自身函數A),這時,因為函數A的位置信息和內部變量已經不會再用到了,直接把函數A的棧幀交給函數B使用。

PS:尾調用優化在Release模式下才會有,Debug模式下沒有。

源碼地址: https://github.com/QiShare/QiRecursiveDemo.git

【本文是51CTO專欄機構360技術的原創文章,微信公眾號“360技術( id: qihoo_tech)”】

戳這里,看該作者更多好文

責任編輯:趙寧寧 來源: 51CTO專欄
相關推薦

2015-08-25 14:25:54

objc_msgsen

2021-07-09 19:04:55

Cache查找消息

2015-08-13 10:28:07

Cobjc_msgSen匯編

2020-09-30 08:07:46

如何優化尾調用

2020-05-27 07:38:36

尾遞歸優化遞歸函數

2010-09-17 13:01:44

Python

2009-07-22 07:44:00

Scala尾遞歸

2015-04-17 16:30:46

swiftOC

2015-03-16 10:17:48

objc照片框架

2018-04-27 09:03:57

Redis數據存儲

2022-05-26 08:31:41

分層機制優化

2021-11-23 10:25:35

性能優化iOS App 啟動優化

2013-10-16 15:36:53

iOS優化

2013-12-17 16:21:17

iOSiOS性能優化

2016-09-20 22:41:21

Linuxmmapreadahead

2021-08-03 07:40:46

Synchronize鎖膨脹性能

2025-03-26 00:55:00

2017-12-18 11:09:45

消息轉發DemoPerson

2021-09-10 15:13:41

鴻蒙HarmonyOS應用

2015-12-23 09:16:33

ios動畫渲染機制
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日本黄色大片免费 | 国产一区二区三区久久久久久久久 | 三级国产三级在线 | 天堂资源 | 国产亚洲精品久久午夜玫瑰园 | 国产精品永久久久久久久www | 欧美激情亚洲天堂 | 亚洲va欧美va天堂v国产综合 | 亚洲97| 午夜三区 | 男女羞羞视频网站 | 国产精品大片在线观看 | 国产91视频播放 | 久久夜视频 | 成人网视频 | 欧美国产视频一区二区 | 玖玖操 | 亚洲精品一区二三区不卡 | 国产在线拍偷自揄拍视频 | 爱综合| 日韩在线一区二区三区 | 瑞克和莫蒂第五季在线观看 | 国产精品99 | 成人一区二区在线 | 久久99精品久久久久久 | 亚洲男人网| 久久最新精品视频 | www.788.com色淫免费 | 日韩欧美在线视频 | 成年人视频免费在线观看 | a网站在线观看 | 久久国产一区二区三区 | 国产在线播放av | 在线观看成人 | 日p视频免费看 | 欧美成人第一页 | 色悠悠久| 久久精品国产一区二区三区 | 激情91 | 男女羞羞免费网站 | 亚洲精品中文字幕av |