Profiler Class Reference#include <Profiler.h>
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 |
| Profiler (unsigned int mx) |
| constructor, but you don't want to construct one of these! Use ProfilerOfSize<x> instead!
|
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 |
static 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 |
static const unsigned int | MaxSectionNameLen = 75 |
| maximum length of names of timers
|
static const unsigned int | HistSize = 32 |
| number of slots in the histograms
|
static const unsigned int | HistTime = 10*1000 |
| the upper bound (exclusive) of the histograms, in milliseconds.
|
static 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 |
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...)
|
Protected Attributes |
Profiler::AutoInit | autoInit |
| Automatically causes initialization of the histogram buckets when the first Profiler is instantiated.
|
Static Protected Attributes |
static float | buckets [HistSize] |
| holds boundaries for each bucket
|
static unsigned int | infosOffset = ((size_t)(&static_cast<ProfilerOfSize<1>*>(NULL)[1].infos))-((size_t)(&static_cast<ProfilerOfSize<1>*>(NULL)[1].prof)) |
| 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.
|
Classes |
class | AutoInit |
| Automatically causes initialization of the histogram buckets when the first Profiler is instantiated. More...
|
struct | SectionInfo |
| holds all the information needed for book keeping for each timer More...
|
class | Timer |
| Measures the time that this class exists, reports result to a profiler. More...
|
Constructor & Destructor Documentation
Profiler::Profiler |
( |
unsigned int |
mx |
) |
|
|
|
constructor, but you don't want to construct one of these! Use ProfilerOfSize<x> instead!
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 151 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 148 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
|
Automatically causes initialization of the histogram buckets when the first Profiler is instantiated.
|
|
affects how linearly the buckets are distributed - 1 means linear, >1 causes higher resolution for short times
Definition at line 99 of file Profiler.h.
Referenced by initBuckets(). |
|
NASTY HACK - this is how we get around using virtual functions.
Definition at line 191 of file Profiler.h.
Referenced by getInfos(). |
|
so we can read the size of the infos array back again at runtime
Definition at line 159 of file Profiler.h.
Referenced by getNewID(). |
The documentation for this class was generated from the following files:
|