performance 测量 C++ 中的异常处理开销
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/43253/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Measuring exception handling overhead in C++
提问by Antti Kissaniemi
What is the best way to measure exception handling overhead/performance in C++?
在 C++ 中测量异常处理开销/性能的最佳方法是什么?
Please give standalone code samples.
请给出独立的代码示例。
I'm targeting Microsoft Visual C++ 2008 and gcc.
我的目标是 Microsoft Visual C++ 2008 和 gcc。
I need to get results from the following cases:
我需要从以下情况中获得结果:
- Overhead when there are no try/catch blocks
- Overhead when there are try/catch blocks but exceptions are not thrown
- Overhead when exceptions are thrown
- 没有 try/catch 块时的开销
- 有 try/catch 块但不抛出异常时的开销
- 抛出异常时的开销
回答by Xavier Nodet
Section 5.4 of the draft Technical Report on C++ Performanceis entirely devoted to the overhead of exceptions.
关于 C++ 性能的技术报告草案的第 5.4 节完全致力于异常的开销。
回答by Carl Seleborg
As a suggestion: don't bother too much with the overhead when exceptions are thrown. Exception handling implementations usually make not throwing fast and catching slow. That's ok since those cases are, well, exceptional.
作为一个建议:当抛出异常时,不要太在意开销。异常处理实现通常不会快速抛出和捕获慢。没关系,因为这些情况非常特殊。
Carl
卡尔
回答by Antti Kissaniemi
Here's the measuring code I came up with. Do you see any problems with it?
这是我想出的测量代码。你看到它有什么问题吗?
Works on Linux and Windows so far, compile with:
到目前为止适用于 Linux 和 Windows,编译:
g++ exception_handling.cpp -o exception_handling [ -O2 ]
or for example Visual C++ Express.
To get the base case ("exception support removed from the language altogether"), use:
要获得基本情况(“完全从语言中删除了异常支持”),请使用:
g++ exception_handling.cpp -o exception_handling [ -O2 ] -fno-exceptions -DNO_EXCEPTIONS
or similar settings in MSVC.
或 MSVC 中的类似设置。
Some preliminary results here. They are probably all hokey because of varying machine load, but they do give some idea about the relative exception handling overhead. (Executive summary: none or little when no exceptions are thrown, huge when they actually are thrown.)
这里有一些初步结果。由于不同的机器负载,它们可能都是假的,但它们确实提供了一些关于相关异常处理开销的想法。(执行摘要:不抛出异常时为 none 或 little,实际抛出时为 big。)
#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
}
回答by cic
Kevin Freitalks about exception handling performance cost in his speech "The Cost of C++ Exception Handling on Windows". (Under "Summary & Conclusions" there is one list item that says "[Exception handling performance cost is] not always measurable".)
Kevin Frei在他的演讲“ Windows 上的 C++ 异常处理的成本”中谈到了异常处理的性能成本。(在“摘要和结论”下有一个列表项,上面写着“[异常处理性能成本] 并不总是可衡量的”。)
回答by Carl Seleborg
Another note on exception handling performance: simple tests don't take caching into account. The try-code and the catch-code are both so small that everything fits in the instruction and data caches. But compilers may try to move the catch-code far away from the try-code, which reduces the amount of code to keep in cache normally, thus enhancing performance.
关于异常处理性能的另一个注意事项:简单测试不考虑缓存。try-code 和 catch-code 都非常小,以至于指令和数据缓存中的所有内容都适合。但是编译器可能会尝试将 catch-code 移到远离 try-code 的地方,这会减少通常保留在缓存中的代码量,从而提高性能。
If you compare exception handling to traditional C-style return-value checking, this caching effect should be taken into account as well (the question is usually ignored in discussions).
如果将异常处理与传统的 C 样式返回值检查进行比较,则还应考虑这种缓存效果(该问题通常在讨论中被忽略)。
Carl
卡尔
回答by Maximilian
There's no really good way to meassure that in code. You would need to use a a profiler.
在代码中没有真正好的方法来衡量它。您将需要使用分析器。
This won't show you directly how much time is spent with exception handling but with a little bit of research you will find out which of the runtime methods deal with exceptions (for example for VC++.NET it's __cxx_exc[...]).
这不会直接向您显示异常处理花费了多少时间,但是通过一些研究,您会发现哪些运行时方法处理异常(例如,对于 VC++.NET,它是 __cxx_exc[...])。
Add their times up and you have the overhead. In our project we used vTunes from Intel which works with both Visual C++ and gcc.
把他们的时间加起来,你就有了开销。在我们的项目中,我们使用了来自 Intel 的 vTunes,它适用于 Visual C++ 和 gcc。
Edit: Well, if you just need a generic number that might work. Thought you had an actual application to profile where you can't just turn off exceptions.
编辑:好吧,如果您只需要一个可能有用的通用数字。认为你有一个实际的应用程序来分析你不能只是关闭异常。
回答by Greg Whitfield
Won't the answer depend on what cleanup has to happen as a result of a throw? If an excpetion is thrown that causes a whole load of objects to go out of scope up the stack, then that will add to the overhead.
答案是否取决于抛出后必须进行的清理工作?如果抛出异常导致整个对象负载超出堆栈的范围,那么这将增加开销。
In other words, I'm not sure if there is a an answer to the 3rd question that is independent of the specifics of the code.
换句话说,我不确定第三个问题是否有独立于代码细节的答案。
回答by Arcane
Full details on how g++ handles exceptions is shown here. It describes it as being for the Itanium architecture, however the general techniques used are the same. It won't tell you exact overhead in terms of time, however you can glean what the rough code overhead will be.
此处显示了有关 g++ 如何处理异常的完整详细信息。它描述为用于 Itanium 体系结构,但是使用的通用技术是相同的。它不会告诉您确切的时间开销,但是您可以了解粗略的代码开销是多少。

