.net異常處理的效能問題

JasonJuly發表於2020-10-28

開發人員社群經常就異常處理的效能問題展開活躍爭論。有人說異常處理效能很差,以至於他們根本就不打算使用。但是,我認為在物件導向平臺中,異常處理不是一個可有可無的東西,而是必須的!另外,假若不用它,有什麼是可以替代的呢?讓方法返回bool值型別標識成功或失敗,還是使用某種錯誤程式碼enum型別?如果真的這樣做,那麼兩個世界中最壞的情況都會發生;CLR和類庫都會丟擲異常而你的程式碼會返回錯誤程式碼。現在你的程式碼兩者都要應對。

異常處理和較常規的報告異常的方式相比,很難看出兩者的效能差異。如果寫程式碼檢查每個方法呼叫的返回值,並將返回值“漏”給呼叫者,應用程式效能將受到嚴重影響。就算不考慮效能,由於要寫程式碼檢查某個方法的返回值,也必須進行大量額外的程式設計,而且出錯的概率的概率也會大增。異常處理是一種好得多的方案。

然而,異常處理也是要付出代價的:非託管程式碼C++編譯器必須生成程式碼來跟蹤哪些物件被成功構造。編譯器還必須生成程式碼,以便在一個異常被捕捉到的時候,呼叫每個已成功構造的物件的析構器。由編譯器擔負這個責任當然是最好的,但它會在應用程式中生成大量薄記程式碼,對程式碼的大小和執行時間造成負面影響。

另一方面,託管編譯器就要輕鬆得多,因為託管物件是在託管堆中分配的,而託管堆受垃圾回收器的監視。如果一個物件成功構造,而且丟擲一個異常,垃圾回收器最終會釋放物件的記憶體。編譯器無需生成任何薄記程式碼來跟蹤成功構造的物件,也無需保證析構器的呼叫。與託管C++相比,這意味著編譯器生成的程式碼更少,執行時要執行的程式碼更少,應用程式的效能更好。