PCSX2 Documentation/C++ exceptions can be an optimization: Difference between revisions

no edit summary
No edit summary
No edit summary
Line 1: Line 1:
{{DocTabs|Section=3}}
''Originally written by Jake Stine''
''Originally written by Jake Stine''


Line 10: Line 9:
Typically in traditional error handling models, you check the return code of a function for errors, like so:
Typically in traditional error handling models, you check the return code of a function for errors, like so:


<nowiki>
<source lang="cpp">
if( DoSomethingSpecial() == SPECIAL_FAIL )
if( DoSomethingSpecial() == SPECIAL_FAIL )
{
{
     // Handle error.
     // Handle error.
}</nowiki>
}
</source>


This is simple, short, and quite fast compared to the overhead of entering a C++ try/catch block. But let's consider a more practical everyday example:
This is simple, short, and quite fast compared to the overhead of entering a C++ try/catch block. But let's consider a more practical everyday example:


<nowiki>
<source lang="cpp">
int DoSomethingSpecial()
int DoSomethingSpecial()
{
{
Line 35: Line 35:
         // code [...]
         // code [...]
     } while( DoSomethingSpecial() != SPECIAL_FAIL )
     } while( DoSomethingSpecial() != SPECIAL_FAIL )
}</nowiki>
}
</source>


The above code snippet must perform no less than two conditional checks per loop just to propagate the error code up the chain of function calls, and this isn't even handling the possibility of a function returning more than one error code yet! This is a situation where C++ Exception Handling can come to our rescue:
The above code snippet must perform no less than two conditional checks per loop just to propagate the error code up the chain of function calls, and this isn't even handling the possibility of a function returning more than one error code yet! This is a situation where C++ Exception Handling can come to our rescue:


<nowiki>
<source lang="cpp">
void DoSomethingSpecial()
void DoSomethingSpecial()
{
{
Line 46: Line 47:
     // Do stuff based on DoSomethingElse's success
     // Do stuff based on DoSomethingElse's success
     Console::WriteLn( "Success!" );
     Console::WriteLn( "Success!" );
}</nowiki>
}
</source>


<nowiki>
<source lang="cpp">
void LoopOfCode()
void LoopOfCode()
{
{
Line 61: Line 63:
     }
     }
}
}
</nowiki>
</source>


The above C++ snippet performs the exact same operation, except now no conditionals are needed. We've traded off the two conditionals per loop for the entry/exit code for the try/catch block. But the block is outside the loop, so it will be run only once. Conditional checks are one of the slower operations on almost any CPU design, which means if the loop is a busy one which spins frequently this C++ code will certainly be a significant speedup over the plain jane C version. And that's just with one return code. Adding multiple exception handlers doesn't impact performance at all, so in a case where there are multiple return codes the C++ exception handling approach shines even brighter.
The above C++ snippet performs the exact same operation, except now no conditionals are needed. We've traded off the two conditionals per loop for the entry/exit code for the try/catch block. But the block is outside the loop, so it will be run only once. Conditional checks are one of the slower operations on almost any CPU design, which means if the loop is a busy one which spins frequently this C++ code will certainly be a significant speedup over the plain jane C version. And that's just with one return code. Adding multiple exception handlers doesn't impact performance at all, so in a case where there are multiple return codes the C++ exception handling approach shines even brighter.


... thus dies the age-old rumor that C++ is slower than C. IT's all in how you wield your sword. Or... well... programming language.
... thus dies the age-old rumor that C++ is slower than C. It's all in how you wield your sword. Or... well... programming language.


Edit: I should add that the basic theory of optimization I'm using here is what I call "optimizing for the common case." It's a process of speeding up the code that's being run more frequently (which in our example above is a typically error-free running loop) by offloading the logic to an area of the code that's run much less frequently (the exception handler's entry/exit overhead). It's one of the most powerful optimization techniques any programmer can employ.
Edit: I should add that the basic theory of optimization I'm using here is what I call "optimizing for the common case." It's a process of speeding up the code that's being run more frequently (which in our example above is a typically error-free running loop) by offloading the logic to an area of the code that's run much less frequently (the exception handler's entry/exit overhead). It's one of the most powerful optimization techniques any programmer can employ.


{{PCSX2 Developers Blog Navbox}}
{{PCSX2 Documentation Navbox}}
ninja
782

edits