More Effective C++ 15:瞭解異常處理的系統開銷

爲了在運行時處理異常,程序要記錄大量的信息。
無論執行到什麼地方,程序都必須能夠識別出如果在此處拋出異常的話,將要被釋放哪一個對象;對於每一個 try 塊,他們都必須跟蹤與其相關的 catch 子句以及這些catch子句能夠捕獲的異常類型

不使用任何異常處理特性也要付出代價

你需要空間建立數據結構來跟蹤對象是否被完全構造,你也需要 CPU 時間保持這些數據結構不斷更新。這些開銷一般不是很大,但是採用不支持異常的方法編譯的程序一般比支持異常的程序運行速度更快所佔空間也更小。

理論上,你不能對這些代價進行選擇:異常是 C++的一部分,C++編譯器必須支持異常。

也就是說,當你不用異常處理時你不能讓編譯器生產商消除這方面的開銷,因爲程序一般由多個獨立生成的目標文件組成,只有一個目標文件不進行異常處理並不能代表其他目標文件不進行異常處理。而且即使組成可執行文件的目標文件都不進行異常處理,那麼還有它們所連接的程序庫呢?如果程序的任何一部分使用了異常,其它部分必須
也支持異常。否則在運行時程序就不可能提供正確的異常處理。

異常處理的第二個開銷

第二個開銷來自於 try 塊,無論何時使用它,也就是當你想能夠捕獲異常時,那你都得爲此付出代價。

粗略地估計,如果你使用 try 塊,代碼的尺寸將增加 5%-10%並且運行速度也同比例減慢。這還是假設程序沒有拋出異常,討論的只是在程序裏使用 try塊的開銷。爲了減少開銷,你應該避免使用無用的 try 塊。

編譯器爲異常規格生成的代碼與它們爲 try 塊生成的代碼一樣多,所以一個異常規格一般花掉與 try 塊一樣多的系統開銷。

拋出異常的開銷

與一個正常的函數返回相比,通過拋出異常從函數裏返回可能會慢三個數量級。這個開銷很大。但是僅僅當你拋出異常時纔會有這個開銷,一般不會發生。

總結

爲了使你的異常開銷最小化,只要可能就儘量採用不支持異常的方法編譯程序,把使用 try 塊和異常規格限制在你確實需要它們的地方,並且只有在確爲異常的情況下才拋出異常。如果你在性能上仍舊有問題,總體評估一下你的軟件以決定異常支持是否是一個起作用的因素。如果是,那就考慮選擇其它的編譯器,能在 C++異常處理方面具有更高實現效率的編譯器。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章