Sign in to follow this  
redshock

Performance with using exceptions in C++ game programming

Recommended Posts

In the past, books stated that exception handling was slow for C++ and game dev. The books suggested to call std::nothrow when allocating memory, for example, and then using an if condition to see if the pointer is null or not. These days, I'm not sure. My assumption is it's fast these days. Has there been a best practice for using exception handling these days for games? 

Edited by redshock

Share this post


Link to post
Share on other sites

Interesting. I guess I'll continue to avoid them then unless it's necessary. Thanks for the thoughts. 

Share this post


Link to post
Share on other sites

Since C++11 functions not throwing exceptions and marked as such (noexcept) should run with no penalties.

but I pretend that they don't exist in C++

Interesting. I'm so far from the console world...

So I suppose you never use STL neither on consoles ? You might also avoid to use references (ie a dynamic_cast that fails on a reference should throw an exception). Or do you still disable exceptions with a compiler flag ? That can also be annoying when using middlewares...

Share this post


Link to post
Share on other sites
You'll find that almost all C++ game middleware will avoid exceptions too, or even just expose a C API for ABI stability reasons :) Lots of users will simply regard middleware that uses exceptions as being "broken", so you'll find it gets "fixed" pretty quickly if they want to sell it to gamedevs. any non-broken middleware should also allow the user to supply function pointers for memory allocation, threaded execution and file system access. i.e. middleware that uses the default 'new' allocator is broken.

Dynamic cast is a code smell and almost has no good use cases... Plus C++ RTTI (which dynamic cast relies on) has an abhorrent implementation so is another feature that most gamedevs will pretend doesn't exist.

The std namespace also used to be very flaky across compilers so old codebases would've banned it. It's fine these days, but a lot of companies already have their own vector/map/etc so stick with their own replacements.
Using std along with a compiler option to disable exceptions is also fine... It just turns every exceptional situation into undefined behaviour, so you better add lots of your own assertions that prove these conditions cannot occur. Likewise, using std without any catch statements puts you in the same boat. In my experience, it's a pretty common boat to be in :)

Share this post


Link to post
Share on other sites

I'm not really sure if dropping support for exceptions in current era is good idea.

Exceptions make code cleaner(for ex. you don't need to pass error code via method return codes or arguments), but they need to be used in exceptional situations(a lot of people abuse use of exceptions and try to hide some high level logic inside of catch block).

About performance, in x64 you don't pay any cost when calling function that may throw, all the cost is moved in case when function actually throws and you need to handle exceptions. But as i said, this should occur in exceptional situations(ex. missing file that should be there, problem with connection etc) and mostly at this time you don't care about performance.

I can't speak about consoles(i've never worked on one), but i bet their differ between architectures, as well in x86 land you pay small cost for every function call as compiler generates code for stack unwinding.

Share this post


Link to post
Share on other sites

In the 10 years I've been in the industry, exceptions have been disabled on every single C++ project. Legacy code didn't use them, library code doesn't use them, game engines don't use them, C libraries can't use them, and most programmers in the industry don't know them well enough to make good use of them anyway.

The implementation of exceptions in C++ has never been particularly good anyway, not just in terms of performance but also in terms of the hoops you have to jump through to make your code fully exception-safe, so this hasn't been as much of a loss as people might think.

Share this post


Link to post
Share on other sites

Thank you for the details.

I'll start to deviate a bit from the original topic...

 

Has anyone here heard about ISO C++ SG14 ? This is the study group from the C++ ISO standard which is studying how C++ could be improved for the game industry (among several others).

 

Here are some links in case you might be interested:

https://isocpp.org/blog/tag/sg14

https://groups.google.com/a/isocpp.org/forum/#!forum/sg14

 

What do people here think about this ? Do you think works like this might imply enough changes in the console hardware, or in the C++ mechanisms to allow such 'broken' things in gaming in a near/far future ?

Share this post


Link to post
Share on other sites

To the extent where they fix things we already use, then yes. For example, most engines roll their own RTTI. If standard RTTI becomes just as effective and efficient, then I can see engines moving over to use that.

To the extent where they fix things we learned to work around or live without, such as exceptions, then no. I don't think anyone is going to retrofit exceptions into existing engines.

Share this post


Link to post
Share on other sites

You'll find that almost all C++ game middleware will avoid exceptions too
*cough* https://raw.githubusercontent.com/KhronosGroup/Vulkan-Hpp/master/vulkan/vulkan.hpp

Sorry, I couldn't resist :)

 

But on a more serious note, to the OP: exception handling is not inherently bad, or slow. Exceptions on consoles suck because they use shitty 10-12 year old compilers. Exceptions under Win32 are slow if you don't use the Microsoft compiler because SEH Exceptions for 32-bit Windows are patented (so the other compilers default to using setjump/longjump which is insane).

Exception handling under Win64 is (almost) zero overhead execution-time wise (not binary size wise, unluckily) unless you actually throw. Go ahead and time it, if calling a non-optimized-out small function some million times takes, say, 4.53 +/- 0.01 seconds, then calling the same function with exception handling will take 4.53+/- 0.01 seconds. Only if you actually throw, things look different. But throwing is an exceptional thing, so that is alright.

 

More important than the fact that exceptions are slow (they are not) is the fact that it is impossible to predict how long the handling will take. It can be anywhere from a dozen cycles to milliseconds (if, for example, a destructor flushes and closes files). Depending on the situation, and in particular depending on your realtime-requirements, this uncertainity may be the one thing that makes them forbidding.

Share this post


Link to post
Share on other sites

The belief in not using exceptions in C++ because they are slow is a classic example of cargo cult programming.

Sure, there are old timers (including me) who remembers MSVC6 and wretchedly slow code introduced by exceptions as a result of a ghastly implementation.  It's been decades since then, and the benefits of exceptions vs. all the alternatives have been demonstrated again and again, and with numbers to back that up.

If you want to be sure your code is comparatively fast or slow, you run timing benchmarks on alternatives.  If you want want to join the school of premature optimization and cargo cult programming, you simply and mindlessly follow dogma.

Share this post


Link to post
Share on other sites

You'll find that almost all C++ game middleware will avoid exceptions too

*cough* https://raw.githubusercontent.com/KhronosGroup/Vulkan-Hpp/master/vulkan/vulkan.hpp
Sorry, I couldn't resist :)
That kind of proves my point :)
They use C for a stable ABI, and then in their C++ wrapper, they let you choose between an API with strict preconditions and undefined behaviour if you violate those contracts, or, an API that tolerates invalid code by implementing a contract validation layer that throws exceptions. If they only had the latter API, it would be regarded as broken and unusable by many users, not to mention being unnecessarily bloated (correct code doesn't need the validation layer)... And if they only had the former, it would be regarded as broken and unusable by a different set of users, not to mention being unnecessarily fragile and error-prone. It's as if C++ is actually two (or more) completely distinct languages.
They're doing the right thing by making a multi-layered API that's usable by everyone.

the benefits of exceptions vs. all the alternatives have been demonstrated again and again, and with numbers to back that up.

Exactly; exception-free C++ code has enormous code maintainability benefits, which is the real reason why no one uses them in serious large scale projects.
( :wink: yes I'm trolling you, Bregma )
It is interesting though that our two different communities have completely different common sense here. My experience with gamedevs has common sense saying that C++ exceptions add a huge amount of extra complexity to the entire code base for very little gain, and that a good use for the construct is extremely rare anyway (we tend to have pseudo-realtime loops made up of many parallel and asynchronous tasks, resulting in call-stacks that have no relationship to task hierarchies anyway)... Meanwhile your experience with professional FOSS app dev has pretty much completely opposite lessons / conclusions :|

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this