[Unity] Delegate 隨便測測 - Random Test on Delegate

隨便測測新一彈。 突發奇想的想測試看看,delegate 的建立階段跟運作階段的效能。測試內容使用 System.Action,另外有加上 event 關鍵字與否的比較區別,CPU 計算時間以 for loop 作相同分量的運算作為比較標準。

結果展示

單次執行的內容是做一次 int 的 Add 運算。 分成兩個階段, Prepare 階段是將所需要的執行次數用 += 累計在 delegate 變數上,結果這部分的運算竟然比 Invoke 還花時間!累加 1000 個 delegate 大約花上 0.1 秒,相較之下 Invoke 根本微不足道。 計算 1000 次所花的時間:

1496819495210

計算 10000 次所花的時間:

1496819102244

計算 1000 次所造成的 GC:

1496819232926

打開 Deep Profiler 發現,會造成大量運算的原因應該是 GC 造成的,每次 delegate 進行 += 運算時,都會執行 Delegate.Combine () 的呼叫,大約一次造成 50KB 的 GC,是個有點微妙的數字,雖然不多但在行動裝置上也不到可以直接忽略的程度。

(10000 次運算時,Deep Profiler 打不開了 …)

10000 數量級的 GC 直接衝到 800MB,達到平均一次運算 80KB 左右的 GC,這在其他文章的參考連結有談過,delegate 累加的運算 GC 是一個指數關係,也就是疊越多越吃記憶體。

不過反過來說,沒有一次用到 100 數量級以上的累加 delegate 應該都不用太擔心,注意不要頻繁的 delegate add/remove 運算即可。

後話

本來是在想說,因為 MonoBehaviour 的 Update 是一個呼叫成本很高的 Message,所以一般不會希望一個場景中所有的物件都有各自的 Update,而是用集中管理的方式來節省呼叫效能。

這次突發奇想的點,就是想看看用 event 來實現集中 Update 的效果如何,實際上從測試來看應該是可行的,只是也發現到如果在場景啟動時要將所有物件註冊到這個 event 中,會出現可怕的消耗,這點要想辦法解決才行。