在C++中測量異常處理開銷/性能的最佳方法是什麼?在C++中測量異常處理開銷
請給出獨立代碼示例。
我針對Microsoft Visual C++ 2008和gcc。
我需要從以下情況下得到的結果:當沒有try/catch塊當有try/catch塊,但異常不拋出
- 開銷拋出異常
在C++中測量異常處理開銷/性能的最佳方法是什麼?在C++中測量異常處理開銷
請給出獨立代碼示例。
我針對Microsoft Visual C++ 2008和gcc。
我需要從以下情況下得到的結果:當沒有try/catch塊當有try/catch塊,但異常不拋出
建議:在引發異常時不要打擾太多的開銷。異常處理實現通常不會很快並且很慢。沒關係,因爲這些情況是非常特殊的。
卡爾
這是我想出的測量代碼。你看到它有什麼問題嗎?
在Linux和Windows,到目前爲止,編譯:
g++ exception_handling.cpp -o exception_handling [ -O2 ]
或例如Visual C++ Express。在MSVC
g++ exception_handling.cpp -o exception_handling [ -O2 ] -fno-exceptions -DNO_EXCEPTIONS
或類似的設置:
要得到基本情況(「異常支持的語言完全刪除」),使用。
一些初步結果here。由於機器負載的變化,它們可能都很麻煩,但它們確實給出了一些有關異常處理開銷的想法。 (內容提要:沒有或很少在沒有拋出異常,巨大時,他們實際上都扔。)
#include <stdio.h>
// Timer code
#if defined(__linux__)
#include <sys/time.h>
#include <time.h>
double time()
{
timeval tv;
gettimeofday(&tv, 0);
return 1.0 * tv.tv_sec + 0.000001 * tv.tv_usec;
}
#elif defined(_WIN32)
#include <windows.h>
double get_performance_frequency()
{
unsigned _int64 frequency;
QueryPerformanceFrequency((LARGE_INTEGER*) &frequency); // just assume it works
return double(frequency);
}
double performance_frequency = get_performance_frequency();
double time()
{
unsigned _int64 counter;
QueryPerformanceCounter((LARGE_INTEGER*) &counter);
return double(counter)/performance_frequency;
}
#else
# error time() not implemented for your platform
#endif
// How many times to repeat the whole test
const int repeats = 10;
// How many times to iterate one case
const int times = 1000000;
// Trick optimizer to not remove code
int result = 0;
// Case 1. No exception thrown nor handled.
void do_something()
{
++result;
}
void case1()
{
do_something();
}
// Case 2. No exception thrown, but handler installed
#ifndef NO_EXCEPTIONS
void do_something_else()
{
--result;
}
void case2()
{
try
{
do_something();
}
catch (int exception)
{
do_something_else();
}
}
// Case 3. Exception thrown and caught
void do_something_and_throw()
{
throw ++result;
}
void case3()
{
try
{
do_something_and_throw();
}
catch (int exception)
{
result = exception;
}
}
#endif // !NO_EXCEPTIONS
void (*tests[])() =
{
case1,
#ifndef NO_EXCEPTIONS
case2,
case3
#endif // !NO_EXCEPTIONS
};
int main()
{
#ifdef NO_EXCEPTIONS
printf("case0\n");
#else
printf("case1\tcase2\tcase3\n");
#endif
for (int repeat = 0; repeat < repeats; ++repeat)
{
for (int test = 0; test < sizeof(tests)/sizeof(tests[0]); ++test)
{
double start = time();
for (int i = 0; i < times; ++i)
tests[test]();
double end = time();
printf("%f\t", (end - start) * 1000000.0/times);
}
printf("\n");
}
return result; // optimizer is happy - we produce a result
}
有以meassure,在代碼中沒有真正的好辦法。你需要使用一個分析器。
這不會直接向您顯示在異常處理上花了多少時間,但通過一點研究,您將瞭解哪些運行時方法處理異常(例如,對於VC++ .NET,它是__cxx_exc [.. 。])。
增加他們的時間,你有開銷。在我們的項目中,我們使用了來自Intel的vTunes,它與Visual C++和gcc一起工作。
編輯:好吧,如果你只需要一個可能工作的通用數字。以爲你有一個真正的應用程序來配置你不能關閉異常的地方。
draft Technical Report on C++ Performance的第5.4節完全致力於異常的開銷。
這可以通過引用答案中的相關內容來改進,以防鏈接死機。 – OMGtechy 2015-06-09 14:15:35
有關異常處理性能的另一個注意事項:簡單測試不考慮高速緩存。 try-code和catch-code都很小,一切都適合指令和數據緩存。但是編譯器可能會嘗試將catch代碼從try-code移開,這會減少正常保存在cache中的代碼量,從而提高性能。
如果您將異常處理與傳統的C樣式返回值檢查進行比較,那麼也應該考慮此緩存效果(在討論中通常會忽略此問題)。
卡爾
不會答案取決於什麼清理已發生的拐的結果呢?如果拋出一個引起整個負載的對象超出堆棧的範圍,那麼這會增加開銷。
換句話說,我不確定是否對第三個問題的答案獨立於代碼的具體情況。
Kevin Frei在他的發言「The Cost of C++ Exception Handling on Windows」中討論了異常處理性能成本。 (在「摘要&結論」中有一個列表項目指出「異常處理性能成本並非總是可測量的」。)
有關g ++如何處理異常的完整詳細信息,請參閱here。它將其描述爲用於Itanium體系結構,但所用的一般技術是相同的。它不會告訴你在時間上的確切開銷,但是你可以收集粗略的代碼開銷。
我會對您的平臺上的結果感興趣... – 2008-09-23 20:47:30
您是否試圖做一個測試,你會發現任何異常(catch(...))。它可能不只是捕捉一個異常類... – 2008-09-23 20:48:59