Profiler Class Reference#include <Profiler.h>
Inheritance diagram for Profiler:
[legend]List of all members.
Detailed Description
Managers a hierarchy of timers for profiling time spent in code, gives microsecond resolution.
Doesn't use any pointers so it's safe to put this in shared memory regions.
That's handy so one process can collate all the profiling information across processes to give a summary report to the user.
Example usage:
- Use a static variable to hold an id number for the code section (doesn't necessarily have to be static, but is faster that way)
- Create a Profiler::Timer object - its construction marks the 'start' time, and its destructor marks the 'stop' time.
However, there's a macro that makes this a one liner:
The idea is similar to that used by MMAccessor. If you want to profile a section at smaller resolution than a function, you can use tricks shown in MMAccessor's documentation to limit the timer's scope.
Here were the constraints I set for myself:
- Processes can read each other's Profilers - so must be able to live in shared memory
This is so one process can generate a report on performance of the entire system at once - Flexible memory footprint
MainObject will probably have a lot of subsections. MotionObject won't. Since SectionInfo takes some significant memory space, we don't want to force MotionObject to needlessly make a lot of them. - Flexible usage - can have a single generic global, as well as creating multiple
- Fast - don't want to kill performance of profiled sections, or throw off reported results
Consessions made:
- Sections are not dynamically allocated
- Sections within a Profiler are mutually exclusive (otherwise curSection won't be reliable)
- Results don't try to take affects of pre-emptive multitasking into account.
Global readability is first priority since generating reports is the primary usage, thus we have to be able to handle being in shared memory space. This means no virtual functions and no pointer storage. Unfortunately, this makes the second constraint rather difficult.
Run-time dynamic allocation is right out. But the number of sections is set at compile time anyway, so it should be OK to set this at compile time, using a template parameter.
That gets us 99% of the way there, but it can be burdensome to use this since the template means there's no consistant type for all profilers - you can't have a generic Profiler type if it's templated - you would have to know the size of the profiler you're referring to.
That kind of brings in the third constraint... Instead of accepting a single global, I decided to make a general base (Profiler) and then a templated subclass to hold the bulk data section. This has the nice side affect of not having to specify the bulk of the code in the header, but has the downside that accessing the info stored in the subclass from the super class is very much a hack. If you think you can get around this, good luck!
- Note:
- This could be made much prettier if we didn't care about the virtual function-shared memory problems... sigh
Definition at line 87 of file Profiler.h.
|
Public Member Functions |
unsigned int | getNewID (const char *name) |
| call this to get a new ID number
|
float * | getBuckets () |
| returns the bucket boundaries
|
std::string | report () |
| outputs profiling information
|
void | reset () |
| resets profiling information
|
SectionInfo * | getInfos () |
| gets the actual storage area of the SectionInfo's
|
Static Public Member Functions |
void | initBuckets () |
| called during process init (before any profiled sections)
|
Public Attributes |
unsigned int | curSection |
| the current timer
|
TimeET | startTime |
| time of beginning profiling
|
float | gamma |
| gamma to use with exponential averages (1 to freeze, 0 to set to last)
|
const unsigned int | maxSections |
| so we can read the size of the infos array back again at runtime
|
unsigned int | sectionsUsed |
| the number of timer IDs which have been assigned
|
Static Public Attributes |
const unsigned int | MaxSectionNameLen = 75 |
| maximum length of names of timers
|
const unsigned int | HistSize = 32 |
| number of slots in the histograms
|
const unsigned int | HistTime = 10*1000 |
| the upper bound (exclusive) of the histograms, in milliseconds.
|
const float | HistCurve = 4.05 |
| affects how linearly the buckets are distributed - 1 means linear, >1 causes higher resolution for short times
|
Protected Member Functions |
| Profiler (unsigned int mx) |
| constructor, protected because you don't want to construct one of these - use ProfilerOfSize<x>!
|
void | setCurrent (Timer &tr) |
| called automatically by Timer() - sets the current timer
|
void | finished (Timer &tr) |
| called automatically by ~Timer() - notes the specified timer as finished (doesn't check if the timer is actually the current one - don't screw up!)
|
unsigned int | getBucket (float t) |
| returns which bucket a time should go in, does a binary search over buckets (unless someone things a log() call would be faster...)
|
Static Protected Attributes |
float | buckets [HistSize] |
| holds boundaries for each bucket
|
unsigned int | infosOffset = offsetof(ProfilerOfSize<1>,infos) |
| NASTY HACK - this is how we get around using virtual functions.
|
Friends |
class | Timer |
| Only the Timer's should be calling setCurrent() and finished() upon the Timer's construction and destruction.
|
Constructor & Destructor Documentation
Profiler::Profiler |
( |
unsigned int |
mx |
) |
[protected] |
|
|
constructor, protected because you don't want to construct one of these - use ProfilerOfSize<x>!
Definition at line 114 of file Profiler.cc. |
Member Function Documentation
void Profiler::finished |
( |
Timer & |
tr |
) |
[protected] |
|
|
called automatically by ~Timer() - notes the specified timer as finished (doesn't check if the timer is actually the current one - don't screw up!)
Definition at line 140 of file Profiler.cc.
Referenced by Profiler::Timer::~Timer(). |
unsigned int Profiler::getBucket |
( |
float |
t |
) |
[inline, protected] |
|
|
returns which bucket a time should go in, does a binary search over buckets (unless someone things a log() call would be faster...)
Definition at line 174 of file Profiler.h.
Referenced by finished(), and setCurrent(). |
float* Profiler::getBuckets |
( |
|
) |
[inline] |
|
|
returns the bucket boundaries
Definition at line 145 of file Profiler.h. |
unsigned int Profiler::getNewID |
( |
const char * |
name |
) |
|
|
void Profiler::initBuckets |
( |
|
) |
[static] |
|
std::string Profiler::report |
( |
|
) |
|
|
|
resets profiling information
Definition at line 107 of file Profiler.cc. |
void Profiler::setCurrent |
( |
Timer & |
tr |
) |
[protected] |
|
Friends And Related Function Documentation
friend class Timer [friend]
|
|
Member Data Documentation
|
affects how linearly the buckets are distributed - 1 means linear, >1 causes higher resolution for short times
Definition at line 4 of file Profiler.cc.
Referenced by initBuckets(). |
|
NASTY HACK - this is how we get around using virtual functions.
Definition at line 8 of file Profiler.cc.
Referenced by getInfos(). |
|
so we can read the size of the infos array back again at runtime
Definition at line 156 of file Profiler.h.
Referenced by getNewID(). |
The documentation for this class was generated from the following files:
|