2011-07-06 68 views
5

我處於一種情況,我有具有虛函數Update()的遊戲對象。有很多遊戲對象(目前有7000多個),循環調用所有的遊戲對象(除其他外)。我的同事建議我們應該完全刪除虛擬功能。正如你可以想象的,這將需要大量的重構。在一個緊密的循環中虛擬函數的成本

我見過this answer但在我的情況下,分析意味着我必須更改很多代碼。所以,在我甚至想到開始之前,我想我會問在這裏詢問重構是否值得在這種情況下。

請注意,我已經分析了循環的其他部分,並試圖優化耗時最長的部分。我懷疑這種情況下的虛函數調用是我不應該擔心的事情,但直到我更改代碼(這是很多)之前我無法確定。還要注意一些更新函數非常小,而其他更大更復雜。

編輯:有多種答案可以提供很好的洞察力,所以任何在將來遇到這個問題的人都會看到所有的答案,而不僅僅是選定的答案。

+2

從您提供的信息看來,重構可能很困難或不可能。原因是有幾種不同的Update()函數。重構所得到的結果是,虛擬函數調用將被switch-case或if語句所取代,這在性能上並沒有更好的表現。 – tp1

+2

怎麼敢有人問關於優化的任何事情! :P ...像往常一樣,這些類型的問題-1沒有解釋爲什麼。無論如何,感謝所有回覆的人。我需要的是另一個意見,我得到了。不知道爲什麼有些人會埋頭埋葬一切,甚至有什麼甚至有'優化'這個詞 – Samaursa

+0

同樣在這裏。我正在開發自己的遊戲引擎,目前在線機器上運行速度約爲10fps。不知道去哪裏看,但我不敢問。在我的引擎中,我使用了兩個列表,一個用於所有對象(其數量超過我係統中的活動對象 - 衝突不會使對象處於活動狀態),另一個用於活動對象。 – dascandy

回答

6

如果你不能簡介,看一下彙編代碼來了解一個想法是多麼昂貴的查找真的。這可能是一個簡單的間接跳躍,幾乎沒有任何成本。

如果您需要重構,這裏有一個建議:創建大量的「UpdateXxx」類,它們知道如何調用新的非虛擬update()方法。收集這些數據,然後致電update()

但我的猜測是,你不會節省很多,尤其是沒有隻有7K的對象。

關於性能分析的注意事項:如果您不能使用性能分析器(讓我想知道爲什麼不),請撥打update()的時間以及需要比100ms更長的日誌調用。時間不是很昂貴,它可以讓你快速找出哪些通話費用最高。

+0

這是一個非常好的建議。考慮到你和dascandy的回答,我現在會忘記這一點,但在業餘時間會給你一個建議,看看會發生什麼(+1) – Samaursa

10

虛擬函數調用不會添加遠遠超過單個間接和難以預測的跳轉。這意味着通常每個虛擬函數都會有一個管道沖洗或大約20個循環。其中7000個是大約140000個週期,與您的平均更新功能相比,這應該可以忽略不計。如果不是,那麼說你的更新函數大部分都是空的,你可以考慮把可更新對象放在一個單獨的列表中用於這個目的。

刪除虛擬功能只會導致您將其中一個替換爲相同但自我實現的系統。這是虛擬功能有意義的地方。

根據參考,140000個週期約爲50微秒。這是假設一個龐大的管道P4,並且總是充滿管道沖洗(你通常不會得到)。

+0

非常好,那肯定會對我的決定有所幫助,謝謝(+1) – Samaursa

8

儘管這不是相同的代碼和你可能不相同的編譯器使用,這裏是從一個比較舊的基準(替補++喬Orost)有點參考數據:

Test Name: F000005       Class Name: Style 
CPU Time:  7.70 nanoseconds   plus or minus  0.385 
Wall/CPU:  1.00 ratio.    Iteration Count: 1677721600 
Test Description: 
Time to test a global using a 10-way if/else if statement 
compare this test with F000006 


Test Name: F000006       Class Name: Style 
CPU Time:  2.00 nanoseconds   plus or minus  0.0999 
Wall/CPU:  1.00 ratio.    Iteration Count: 1677721600 
Test Description: 
Time to test a global using a 10-way switch statement 
compare this test with F000005 


Test Name: F000007       Class Name: Style 
CPU Time:  3.41 nanoseconds   plus or minus  0.171 
Wall/CPU:  1.00 ratio.    Iteration Count: 1677721600 
Test Description: 
Time to test a global using a 10-way sparse switch statement 
compare this test with F000005 and F000006 


Test Name: F000008       Class Name: Style 
CPU Time:  2.20 nanoseconds   plus or minus  0.110 
Wall/CPU:  1.00 ratio.    Iteration Count: 1677721600 
Test Description: 
Time to test a global using a 10-way virtual function class 
compare this test with F000006 

這個特殊的結果是用VC++ 9.0(VS 2008)的64位版本的編譯,但它是合理的類似於我從其他最近的編譯器中看到的。最重要的是,虛擬功能比大多數明顯的替代方案都要快,並且它的速度接近相同的速度(實際上,兩者相等在測量誤差範圍內)。但是,這取決於所涉及的密集值 - 正如您在F00007中所看到的,如果值很稀疏,則switch語句會生成比虛擬函數調用更慢的代碼。

底線:虛擬函數調用可能是錯誤的地方。重構後的代碼可能會變得更慢,甚至最多也許無法獲得足夠的注意力或關注。

+0

哇,非常好,謝謝你花時間做這件事。它鞏固了我不擔心的決定(+1) – Samaursa

+0

+1作爲一種事後的想法:C++已經存在了幾年,硬件開發人員已經開始構建可以高效運行的CPU並不奇怪。 :-) –

+0

@Jerry:你可以提供一個鏈接到任何機會來源?我似乎無法獲得板凳的搜索結果++ – Samaursa

相關問題