Swift函式派發優化

2021-10-02 01:54:16 字數 2646 閱讀 5740

與許多其他語言一樣,swift允許類重寫其父類中宣告的方法和屬性。

這意味著程式必須在執行時確定要引用哪個方法或屬性,然後執行間接呼叫或間接訪問。

這種稱為動態排程的技術以每次間接使用時恆定的執行時開銷為代價提高了語言的表達能力。

在對效能敏感的**中,我們不希望花費這些開銷。

這篇部落格文章展示了通過消除這種動態性來提高效能的三種方法:final,private和whole module optimization。

看一下以下示例:

class

particlemodel

func

update

(newp:

(double

,double

), newv:

double)}

var p =

particlemodel()

for i in

stride

(from:

0.0, through:

360, by:

1.0)

按照編寫的方式,編譯器將發出乙個動態排程指令:

變數p呼叫update函式.

變數p的update函式又呼叫了updatepoint函式.

獲取p的point元組屬性.

獲取p的velocity屬性.

這可能不是你所希望看到的。但是動態呼叫是必需的,因為particlemodel的子類可能會重寫屬性point和velocity,或者使用新的實現覆蓋updatepoint或update函式。

在swift中,動態排程呼叫是通過從函式表中查詢函式然後執行間接呼叫來實現的(函式表派發),這比直接派發要慢。

此外,間接呼叫還會阻止許多編譯器優化,從而使間接呼叫的成本更高。

在對效能有要求的**中,有一些技巧可以用來限制不需要提高效能的動態行為。

final關鍵字可以限制類,方法,或者屬性被子類重寫,這使編譯器可以安全地消除動態排程間接定址,例如,在下面的point和velocity屬性將通過物件的儲存屬性中直接訪問,而updatepoint將被直接派發。另一方面,update仍將通過動態排程來呼叫,從而允許子類可以重寫update方法:

class

particlemodel

func

update

(newp:

(double

,double

), newv:

double

)}

通過將屬性附加到類本身,可以將整個類標記為final。這禁止對類進行子類化,這意味著該類的所有功能和屬性也都是final。

final

class

particlemodel

將private關鍵字應用於宣告會限制該宣告對當前檔案的可見性。這使編譯器可以找到所有可能覆蓋的宣告。缺少任何此類覆蓋宣告,可使編譯器自動推斷final關鍵字,並刪除對方法和屬性訪問的間接呼叫。

假如沒有什麼類在當前檔案中重寫particlemodel,編譯器可以將所有的動態分派呼叫與直接呼叫用私有宣告代替。

class

particlemodel

func

update

(newp:

(double

,double

), newv:

double

)}

與前面的示例一樣,子類不能直接訪問point和velocity,並不能直接呼叫updatepoint。因為update不是私有方法,因此可以再次被子類重寫和呼叫。

就像final一樣,可以將private屬性應用於類宣告本身,從而導致該類是私有的,因此也可以讓該類的所有屬性和方法都變為私有。

private

class

particlemodel

具有內部訪問許可權的宣告(如果未宣告,則為預設值)僅在宣告它們的模組中可見。

由於swift通常單獨編譯組成模組的檔案,所以編譯器無法確定是否在其他檔案中重寫了內部宣告。

但是,如果啟用了整個模組優化,則所有模組將同時編譯在一起。

這允許編譯器一起對整個模組進行推斷,並在沒有可見重寫的情況下對內部宣告進行final推斷。

讓我們回到原始**段,這一次向particlemodel新增了一些額外的public關鍵字:

public

class

particlemodel

public

func

update

(newp:

(double

,double

), newv:

double)}

var p =

particlemodel()

for i in

stride

(from:

0.0, through:

360, by:

1.0)

在使用整個模組優化編譯此**段時,編譯器可以根據屬性point、velocity和方法updatepoint推斷是需要用final關鍵字修飾的。

相反,update不用final關鍵字修飾,因為update具有公共訪問許可權。

Swift 的函式派發理解

參考 對於編譯型的語言,函式派發的三種基礎模式分別是 直接派發 direct dispatch 也可以理解外,直接呼叫 不需要曲線救國 函式表派發 table dispatch 物件導向的語言中,一般都會有類的概念,類 用乙個陣列來儲存類中的函式指標,通過此列表 去找 對應的函式 這種派發 催生了 ...

初探Swift函式的派發方式

函式派發就是程式判斷使用哪種途徑去呼叫乙個函式的機制.每次函式被呼叫時都會被觸發,但你又不會太留意的乙個東西.了解派發機制對於寫出高效能的 來說很有必要,而且也能夠解釋很多 swift 裡 奇怪 的行為.編譯型語言有三種基礎的函式派發方式 直接派發 direct dispatch 函式表派發 tab...

swift 函式 函式指標

main.swift functiontest 04 import foundation println 函式測試 testfunction functiontest.swift functiontest 04 import foundation 函式以func開頭 表示是乙個函式 引數和引數以,v...