Scoped Profiler
by Jim McCann · 07/11/2006 (12:42 pm) · 8 comments
Classically, one uses the TGE profiler as follows:
With many return statements (or other scope-exiting events, if you are just profiling, say, the body of a loop) placing all the PROFILE_END calls can be a hassle. Using the innate scope-tracking ability of C++ objects, we can do better:
(I placed the above near the non-empty definitions of PROFILE_START and PROFILE_END in profiler/profiler.h, and an empty definition of PROFILE_SCOPE near the empty definitions of the aforementioned.)
Now all that is required is one call at the begining of the scope you wish to profile. Since the objects destructor is called excactly when it goes out of scope, you don't have to worry about placing PROFILE_END() calls.
Thus, our example becomes:
I hope you find this code useful.
void function_to_profile()
{
PROFILE_START(function_to_profile);
/* ... code ... */
if ( something )
{
PROFILE_END();
return;
}
/* ... more code ... */
PROFILE_END();
}With many return statements (or other scope-exiting events, if you are just profiling, say, the body of a loop) placing all the PROFILE_END calls can be a hassle. Using the innate scope-tracking ability of C++ objects, we can do better:
class ScopedProfiler {
public:
ScopedProfiler(ProfilerRootData *data) {
if (gProfiler) gProfiler->hashPush(data);
}
~ScopedProfiler() {
if (gProfiler) gProfiler->hashPop();
}
};
#define PROFILE_SCOPE(name) \
static ProfilerRootData pdata##name##obj (#name); \
ScopedProfiler scopedProfiler##name##obj(&pdata##name##obj);(I placed the above near the non-empty definitions of PROFILE_START and PROFILE_END in profiler/profiler.h, and an empty definition of PROFILE_SCOPE near the empty definitions of the aforementioned.)
Now all that is required is one call at the begining of the scope you wish to profile. Since the objects destructor is called excactly when it goes out of scope, you don't have to worry about placing PROFILE_END() calls.
Thus, our example becomes:
void function_to_profile()
{
PROFILE_SCOPE(function_to_profile);
/* ... code ... */
if ( something )
{
return;
}
/* ... more code ... */
}I hope you find this code useful.
#2
07/11/2006 (2:36 pm)
Extremely handy - this should become a standard part of the profiler. Great work!
#3
PROFILE_SCOPE(block_to_profile){
... code ...
}
This way, you can have multiple and nested profiles going easily. With the approach above, it could be harder to do both.
07/11/2006 (4:20 pm)
It would be slightly more useful if you can change the macro so it can start a block, like so:PROFILE_SCOPE(block_to_profile){
... code ...
}
This way, you can have multiple and nested profiles going easily. With the approach above, it could be harder to do both.
#4
Indeed, the destructor will be called at closing braces, so you can still profile block. You can even add braces to have specific block if you want
07/13/2006 (5:24 am)
It should work if you put it that way:toto()
{
PROFILE_SCOPE(main);
/* code ... */
if(something) {
PROFILE_SCOPE(sub1);
/** code **/
}
}Indeed, the destructor will be called at closing braces, so you can still profile block. You can even add braces to have specific block if you want
#5
07/19/2006 (6:56 pm)
Very useful resource, thanks for this!
#6
07/22/2006 (9:14 am)
Excellent! Thanks for this!
#7
07/28/2006 (9:01 pm)
Nice thing. I've been working on an upgrade to the profiler in my spare time, and trying to get something like that works 100% with the existing profile start and end blocks - basically making end optional. This is much simpler to do, and about 99% as useful!
#8
07/31/2006 (10:42 am)
Being an enthusiastic C++ programmers, I always welcome the introduction of C++ idioms, especially when they are more powerful than their C counterparts (that is: most of the times)! Kudos to Jim! 
Torque 3D Owner Jesse Liles