2010-10-29 64 views
35

在閱讀問題之前:
這個問題不是關於如何使用dynamic_cast。它只是關於它的表現。dynamic_cast的性能?

我最近開發了一個設計,其中dynamic_cast用於很多。
當與同事討論時,幾乎所有人都說dynamic_cast不應該使用,因爲它的表現不好(這些人是不同背景的同事,在某些情況下彼此不認識,我在大公司)

我決定測試這種方法的性能,而不是僅僅相信它們。

下面的代碼用於:

ptime firstValue(microsec_clock::local_time()); 

ChildObject* castedObject = dynamic_cast<ChildObject*>(parentObject); 

ptime secondValue(microsec_clock::local_time()); 
time_duration diff = secondValue - firstValue; 
std::cout << "Cast1 lasts:\t" << diff.fractional_seconds() << " microsec" << std::endl; 

上述代碼使用從boost::date_time Linux上的方法,以得到有用的值。
我在一次執行中完成了3個dynamic_cast,測量它們的代碼是相同的。

1所執行的結果如下:
Cast1持續74微秒
硬脂酸鈣持續:2微秒
CAST3持續:1微秒

第一鑄造總是把74-111微秒,以下在同樣的執行中投了1-3微秒。

因此最後我的問題:
dynamic_cast真的表現不好嗎?
根據測試結果它沒有。我的測試代碼是否正確?
爲什麼這麼多開發者認爲如果它不是很慢呢?

+13

我錯過了什麼嗎?我看不到cast2或cast3的任何代碼。 – Flexo 2010-10-29 10:17:24

+4

誰能說什麼不好?你的程序的表現是否足夠好?如果是這樣,那麼表現並不差。動態總時間是否會佔用執行時間的很大一部分?如果不是,那麼首先擔心其他事情。更一般地說,對於某些應用程序來說,74微秒的速度非常慢 - 在我上一份工作中,我已經收到並解析了股票交易所的整個更新記錄,更新了數據庫,並在一半時間內向客戶端應用程序通知了它。如果你有興趣,然後將其與其他方式進行比較,以獲得相同的行爲。 – 2010-10-29 10:27:23

+3

在代碼中有很多dynamic_casts是設計問題的一個明確標誌。 – 2010-10-29 11:07:44

回答

42

首先,您需要測量性能而不僅僅是幾次迭代,因爲結果將由定時器的分辨率決定。嘗試100萬以上,以建立一個有代表性的圖片。此外,除非您將其與某些事物進行比較,即做相同的事情,但沒有動態投射,這一結果就沒有意義。其次,您需要確保編譯器不會通過優化同一指針上的多個動態強制轉換(因此使用循環,但每次使用不同的輸入指針),從而不會給您提供錯誤的結果。

動態轉換將會變慢,因爲它需要訪問對象的RTTI(運行時類型信息)表,並檢查轉換是否有效。然後,爲了正確使用它,您需要添加錯誤處理代碼來檢查返回的指針是否爲NULL。所有這些都需要週期。

我知道你不想談這個,但「裏的dynamic_cast使用了很多設計」可能是你正在做的事情錯的指標...

+5

+1,但10K迭代可能是不夠的。有一億比較好。 – sharptooth 2010-10-29 10:38:18

+0

@sharptooth:公平點! – 2010-10-29 10:51:45

+0

@Oliver Charlesworth「...爲了正確使用它,您需要添加錯誤處理代碼來檢查返回的指針是否爲NULL」您提到的檢查的類似版本存在於每種找到一個對象的運行時類型,所以這不是一個參數。 – spectre 2015-10-30 09:54:04

24

性能是毫無意義的比較等效的功能。大多數人都說dynamic_cast比較慢,沒有與同等行爲進行比較。把它們叫出來。換句話說:

如果'工作'不是要求,我可以編寫比你的更快的代碼。

有多種實現dynamic_cast的方法,有些方法比其他方法快。例如,Stroustrup發表了一篇關於使用primes to improve dynamic_cast的論文。不幸的是,控制你的編譯器如何實現強制轉換是非常不尋常的,但是如果性能對你真的很重要,那麼你可以控制你使用的編譯器。

然而,不使用的dynamic_cast將總是比使用更快 - 但如果你實際上並不需要的dynamic_cast,那麼就不要使用它!如果您確實需要動態查找,那麼會有一些開銷,然後您可以比較各種策略。

+4

+1。是的,順便說一句,每個活着的人最終會死。這並不意味着活着是一個壞主意。 – sharptooth 2010-10-29 10:39:28

4

很抱歉地說這個,但是你的測試對於確定演員陣容是否緩慢無效。微秒分辨率遠不夠好。我們正在談論的是一種操作,即使在最壞的情況下,典型PC上的時鐘週期不應超過100個時鐘週期,或者小於50納秒。

毫無疑問,動態演員陣容比靜態演員陣容或者重新演繹演員陣容要慢,因爲在裝配層面上,後兩者相當於一個任務(非常快,1個時鐘刻度的順序),以及動態轉換需要代碼去檢查對象以確定其實際類型。

我不能說它真的是多麼慢,這可能會從編譯器到編譯器不同,我需要看到爲該行代碼生成的彙編代碼。但正如我所說,每次調用50納秒是期望合理的上限。

+0

dynamic_cast需要訪問RTTI,這將需要週期。 – doron 2010-10-29 10:59:28

16

這裏有幾個基準:
http://tinodidriksen.com/2010/04/14/cpp-dynamic-cast-performance/
http://www.nerdblog.com/2006/12/how-slow-is-dynamiccast.html

據他們說,將dynamic_cast比reinterpret_cast的要慢5-30倍,而最好的替代執行幾乎相同的reinterpret_cast。

我會引用第一篇文章的結論是:

  • dynamic_cast的是什麼,但鑄造爲基本類型慢;該 特定鑄造被優化出
  • 繼承級別對dynamic_cast的大的影響
  • 成員變量+的reinterpret_cast是
    確定類型最快可靠的方式;然而,當編碼時

絕對數字是100納秒的單個投的數量級上具有較高的大量維護開銷
。像74毫秒的值似乎並不接近現實。

+1

他得到的價值是74 usec(微秒),而不是74毫秒(毫秒)。即便如此,它仍然不太現實。 – Ponkadoodle 2012-03-18 20:14:55