NLMISC::CHTimer Class Reference

#include <hierarchical_timer.h>


Detailed Description

Hierarchical timing system. Allows to accurately measure performance of routines, and displays results hierarchically. To time a piece of code, just declare a static CHTimer object and encapsulate code between calls to before() and after() methods. ex:
void myFunction() { static CHTimer myTimer("myFunction"); myTimer.before(); // some code here myTimer.after(); } *
Don't forget to call after() to avoid timing wrongness or assertion crashes !

Warning:
Supports only single-threaded applications.

Supports only Intel processors.

Author:
Benjamin Legros

Nicolas Vizerie

Nevrax France

Date:
2001, 2002

Definition at line 187 of file hierarchical_timer.h.

Public Types

enum  TSortCriterion {
  NoSort, TotalTime, TotalTimeWithoutSons, MeanTime,
  NumVisits, MaxTime, MinTime, SortCriterionsLast
}

Public Member Functions

void after (bool displayAfter)
void after ()
void before ()
 Starts a measuring session.

 CHTimer (const char *name, bool isRoot=false)
 CHTimer ()
 ctor

const char * getName () const
void setName (const char *name)

Static Public Member Functions

void adjust ()
void bench ()
bool benching ()
void clear ()
 Clears stats, and reinits all timer structure.

void display (CLog *log=InfoLog, TSortCriterion criterion=TotalTime, bool displayInline=true, bool displayEx=true)
void displayByExecutionPath (CLog *log=InfoLog, TSortCriterion criterion=TotalTime, bool displayInline=true, bool alignPaths=true, bool displayEx=true)
void displayHierarchical (CLog *log=InfoLog, bool displayEx=true, uint labelNumChar=32, uint indentationStep=2)
void displayHierarchicalByExecutionPath (CLog *log=InfoLog, bool displayEx=true, uint labelNumChar=32, uint indentationStep=2)
void displayHierarchicalByExecutionPathSorted (CLog *log=InfoLog, TSortCriterion criterion=TotalTime, bool displayEx=true, uint labelNumChar=32, uint indentationStep=2)
void displaySummary (CLog *log=InfoLog, TSortCriterion criterion=TotalTime, bool displayEx=true, uint labelNumChar=32, uint indentationStep=2, uint maxDepth=3)
void endBench ()
 Ends a bench session.

void startBench (bool wantStandardDeviation=false, bool quick=false, bool reset=true)

Private Types

typedef std::vector< CNode * > TNodeVect
typedef std::vector< CHTimer * > TTimerVect

Private Member Functions

void doAfter (bool displayAfter=false)
void doBefore ()
void walkTreeToCurrent ()

Static Private Member Functions

void estimateAfterStopTime ()

Private Attributes

bool _IsRoot
const char * _Name
CHTimer_Parent
TTimerVect _Sons

Static Private Attributes

sint64 _AfterStopEstimateTime = 0
bool _AfterStopEstimateTimeDone = false
bool _Benching = false
bool _BenchStartedOnce = false
CNode_CurrNode = &_RootNode
CHTimer_CurrTimer = &_RootTimer
double _MsPerTick
CSimpleClock _PreambuleClock
CNode _RootNode
CHTimer _RootTimer
bool _WantStandardDeviation = false


Member Typedef Documentation

typedef std::vector<CNode *> NLMISC::CHTimer::TNodeVect [private]
 

Definition at line 282 of file hierarchical_timer.h.

Referenced by display(), displayByExecutionPath(), and displayHierarchical().

typedef std::vector<CHTimer *> NLMISC::CHTimer::TTimerVect [private]
 

Definition at line 283 of file hierarchical_timer.h.


Member Enumeration Documentation

enum NLMISC::CHTimer::TSortCriterion
 

Enumeration values:
NoSort 
TotalTime 
TotalTimeWithoutSons 
MeanTime 
NumVisits 
MaxTime 
MinTime 
SortCriterionsLast 

Definition at line 191 of file hierarchical_timer.h.

00191                             { NoSort, 
00192                                                   TotalTime,
00193                                                   TotalTimeWithoutSons,
00194                                                   MeanTime,
00195                                                   NumVisits,
00196                                                   MaxTime,
00197                                                   MinTime,
00198                                                   SortCriterionsLast
00199                                                 };


Constructor & Destructor Documentation

NLMISC::CHTimer::CHTimer  )  [inline]
 

ctor

Definition at line 202 of file hierarchical_timer.h.

References _IsRoot.

00202 : _Name(NULL), _Parent(NULL), _IsRoot(false) {}

NLMISC::CHTimer::CHTimer const char *  name,
bool  isRoot = false
[inline]
 

Definition at line 203 of file hierarchical_timer.h.

References _IsRoot.

00203 : _Name(name), _Parent(NULL), _IsRoot(isRoot) {}


Member Function Documentation

void NLMISC::CHTimer::adjust  )  [inline, static]
 

For backward compatibility

Definition at line 234 of file hierarchical_timer.h.

00234 {}

void NLMISC::CHTimer::after bool  displayAfter  )  [inline]
 

Definition at line 216 of file hierarchical_timer.h.

References _Benching, and doAfter().

00217         {
00218                 if (_Benching)
00219                         doAfter(displayAfter);
00220         }

void NLMISC::CHTimer::after  )  [inline]
 

Definition at line 211 of file hierarchical_timer.h.

References _Benching, and doAfter().

Referenced by endBench(), estimateAfterStopTime(), NLMISC::CAutoTimer::~CAutoTimer(), and NLMISC::CAutoTimerInst::~CAutoTimerInst().

00212         {
00213                 if (_Benching)
00214                         doAfter(false);
00215         }

void NLMISC::CHTimer::before  )  [inline]
 

Starts a measuring session.

Definition at line 205 of file hierarchical_timer.h.

References _Benching, and doBefore().

Referenced by NLMISC::CAutoTimer::CAutoTimer(), NLMISC::CAutoTimerInst::CAutoTimerInst(), estimateAfterStopTime(), and startBench().

00206         {
00207                 if (_Benching)
00208                         doBefore();
00209         }

void NLMISC::CHTimer::bench  )  [inline, static]
 

For backward compatibility

Definition at line 231 of file hierarchical_timer.h.

References startBench().

00231 { startBench(); }

bool NLMISC::CHTimer::benching  )  [inline, static]
 

Definition at line 238 of file hierarchical_timer.h.

References _Benching.

00238 { return _Benching; }

void NLMISC::CHTimer::clear  )  [static]
 

Clears stats, and reinits all timer structure.

Definition at line 796 of file hierarchical_timer.cpp.

References _CurrNode, _RootNode, nlassert, and NLMISC::CHTimer::CNode::reset().

Referenced by estimateAfterStopTime(), and startBench().

00797 {
00798         // should not be benching !
00799         nlassert(_CurrNode == &_RootNode);
00800         _RootNode.releaseSons();
00801         _CurrNode = &_RootNode;
00802         _RootNode.reset();      
00803 }

void NLMISC::CHTimer::display CLog log = InfoLog,
TSortCriterion  criterion = TotalTime,
bool  displayInline = true,
bool  displayEx = true
[static]
 

Display results

Parameters:
displayEx true to display more detailed infos

Definition at line 288 of file hierarchical_timer.cpp.

References _BenchStartedOnce, _CurrNode, _MsPerTick, _RootNode, _WantStandardDeviation, NLMISC::CHTimer::CStats::buildFromNode(), NLMISC::CLog::displayNL(), NLMISC::CLog::displayRawNL(), format, NLMISC::CSimpleClock::getNumTicks(), NoSort, NLMISC::CHTimer::CNode::Owner, NLMISC::smprintf(), NLMISC::CHTimer::CNode::Sons, NLMISC::CHTimer::CNode::SonsPreambule, NLMISC::CSimpleClock::start(), NLMISC::CSimpleClock::stop(), TNodeVect, NLMISC::toString(), NLMISC::CHTimer::CStats::TotalTime, and uint.

Referenced by NLSOUND::CSoundDriverDSound::displayBench().

00289 {       
00290         CSimpleClock    benchClock;
00291         benchClock.start();
00292         if(!_BenchStartedOnce) // should have done at least one bench   
00293         {
00294                 benchClock.stop();
00295                 _CurrNode->SonsPreambule += benchClock.getNumTicks();
00296                 return;
00297         }
00298         log->displayNL("HTIMER: =========================================================================");
00299         log->displayRawNL("HTIMER: Bench cumuled results");
00300         typedef std::map<CHTimer *, TNodeVect> TNodeMap;
00301         TNodeMap nodeMap;
00302         TNodeVect nodeLeft;     
00303         nodeLeft.push_back(&_RootNode);
00305         while (!nodeLeft.empty())
00306         {       
00307                 CNode *currNode = nodeLeft.back();
00308                 nodeMap[currNode->Owner].push_back(currNode);
00309                 nodeLeft.pop_back();
00310                 nodeLeft.insert(nodeLeft.end(), currNode->Sons.begin(), currNode->Sons.end());
00311 
00312         }
00313         //      
00314         // 2 ) build statistics 
00315         typedef std::vector<CTimerStat> TTimerStatVect;
00316         typedef std::vector<CTimerStat *> TTimerStatPtrVect;
00317         TTimerStatVect          stats(nodeMap.size());
00318         TTimerStatPtrVect       statsPtr(stats.size());
00319         //
00320         uint k = 0;
00321         for(TNodeMap::iterator it = nodeMap.begin(); it != nodeMap.end(); ++it)
00322         {
00323                 statsPtr[k] = &stats[k];
00324                 stats[k].Timer = it->first;
00325                 stats[k].buildFromNodes(&(it->second[0]), it->second.size(), _MsPerTick);
00326                 ++k;
00327         }
00328         // 3 ) sort statistics
00329         if (criterion != NoSort)
00330         {
00331                 CStatSorter sorter(criterion);
00332                 std::sort(statsPtr.begin(), statsPtr.end(), sorter);            
00333         }
00334 
00335         // 4 ) get root total time.
00336         CStats  rootStats;
00337         rootStats.buildFromNode( &_RootNode, _MsPerTick);
00338 
00339         // 5 ) display statistics
00340         uint maxNodeLenght = 0;
00341         std::string format;
00342         if (displayInline)
00343         {
00344                 for(TTimerStatPtrVect::iterator statIt = statsPtr.begin(); statIt != statsPtr.end(); ++statIt)
00345                 {
00346                         maxNodeLenght = std::max(maxNodeLenght, (uint)strlen((*statIt)->Timer->_Name));
00347                 }
00348                 format = "HTIMER: %-" + NLMISC::toString(maxNodeLenght + 1) + "s %s";
00349         }
00350         std::string statsInline;
00351 
00352         log->displayRawNL(format.c_str(), "", " |      total |      local |       visits |  loc%/ glb% |       min |       max |      mean");
00353 
00354         for(TTimerStatPtrVect::iterator statIt = statsPtr.begin(); statIt != statsPtr.end(); ++statIt)
00355         {
00356                 if (!displayInline)
00357                 {               
00358                         log->displayRawNL("HTIMER: =================================");
00359                         log->displayRawNL("HTIMER: Node %s", (*statIt)->Timer->_Name);          
00360                         (*statIt)->display(log, displayEx, _WantStandardDeviation);
00361                 }
00362                 else
00363                 {
00364                         (*statIt)->getStats(statsInline, displayEx, rootStats.TotalTime, _WantStandardDeviation);
00365                         char out[4096];
00366                         NLMISC::smprintf(out, 2048, format.c_str(), (*statIt)->Timer->_Name, statsInline.c_str());
00367                         log->displayRawNL(out);                                 
00368                 }
00369         }       
00370         benchClock.stop();
00371         _CurrNode->SonsPreambule += benchClock.getNumTicks();
00372 }

void NLMISC::CHTimer::displayByExecutionPath CLog log = InfoLog,
TSortCriterion  criterion = TotalTime,
bool  displayInline = true,
bool  alignPaths = true,
bool  displayEx = true
[static]
 

Display results by execution paths

Parameters:
displayInline true to display each result on a single line.
alignPaths true to display all execution paths aligned.
displayEx true to display more detailed infos.

Definition at line 375 of file hierarchical_timer.cpp.

References _BenchStartedOnce, _CurrNode, _MsPerTick, _RootNode, _WantStandardDeviation, NLMISC::CHTimer::CStats::buildFromNode(), NLMISC::CLog::displayRawNL(), format, NLMISC::CHTimer::CNode::getNumNodes(), NLMISC::CSimpleClock::getNumTicks(), nlassert, NoSort, NLMISC::smprintf(), NLMISC::CHTimer::CNode::Sons, NLMISC::CHTimer::CNode::SonsPreambule, NLMISC::CSimpleClock::start(), NLMISC::CSimpleClock::stop(), TNodeVect, NLMISC::toString(), NLMISC::CHTimer::CStats::TotalTime, and uint.

Referenced by NLSOUND::CSoundDriverDSound::displayBench().

00376 {       
00377         CSimpleClock    benchClock;
00378         benchClock.start();
00379         log->displayRawNL("HTIMER: =========================================================================");
00380         log->displayRawNL("HTIMER: Bench by execution path");
00381         nlassert(_BenchStartedOnce); // should have done at least one bench     
00382         //
00383         typedef std::vector<CNodeStat>   TNodeStatVect;
00384         typedef std::vector<CNodeStat *> TNodeStatPtrVect;
00385 
00386         TNodeStatVect nodeStats;
00387         nodeStats.reserve(_RootNode.getNumNodes());
00388         TNodeVect nodeLeft;     
00389         nodeLeft.push_back(&_RootNode);
00391         while (!nodeLeft.empty())
00392         {       
00393                 CNode *currNode = nodeLeft.back();
00394                 
00395                 nodeStats.push_back(CNodeStat());
00396                 nodeStats.back().buildFromNode(currNode, _MsPerTick);
00397                 nodeStats.back().Node = currNode;
00398 
00399                 nodeLeft.pop_back();
00400                 nodeLeft.insert(nodeLeft.end(), currNode->Sons.begin(), currNode->Sons.end());
00401 
00402         }
00403 
00405         // create a pointer list
00406         TNodeStatPtrVect nodeStatsPtrs(nodeStats.size());
00407         for(uint k = 0; k < nodeStats.size(); ++k)
00408         {
00409                 nodeStatsPtrs[k] = &nodeStats[k];
00410         }
00411 
00412         // 3 ) sort statistics
00413         if (criterion != NoSort)
00414         {
00415                 CStatSorter sorter(criterion);
00416                 std::sort(nodeStatsPtrs.begin(), nodeStatsPtrs.end(), sorter);
00417         }
00418 
00419         // 4 ) get root total time.
00420         CStats  rootStats;
00421         rootStats.buildFromNode(&_RootNode, _MsPerTick);
00422 
00423         // 5 ) display statistics
00424         std::string statsInline;
00425         std::string nodePath;
00426 
00427         std::string format;
00428         if (displayInline)
00429         {
00430                 if (alignPaths)
00431                 {
00432                         uint maxSize = 0;
00433                         std::string np;
00434                         for(TNodeStatPtrVect::iterator it = nodeStatsPtrs.begin(); it != nodeStatsPtrs.end(); ++it)
00435                         {
00436                                 (*it)->Node->getPath(np);
00437                                 maxSize = std::max(maxSize, (uint)np.size());
00438                         }
00439                         format = "HTIMER: %-" + NLMISC::toString(maxSize) +"s %s";
00440                 }
00441                 else
00442                 {
00443                         format = "HTIMER: %s %s";
00444                 }
00445         }
00446 
00447         log->displayRawNL(format.c_str(), "", " |      total |      local |       visits |  loc%/ glb% |       min |       max |      mean");
00448 
00449         for(TNodeStatPtrVect::iterator it = nodeStatsPtrs.begin(); it != nodeStatsPtrs.end(); ++it)
00450         {
00451                 if (!displayInline)
00452                 {               
00453                         log->displayRawNL("HTIMER: =================================");
00454                         (*it)->Node->displayPath(log);
00455                         (*it)->display(log, displayEx, _WantStandardDeviation);
00456                 }
00457                 else
00458                 {
00459                         (*it)->getStats(statsInline, displayEx, rootStats.TotalTime, _WantStandardDeviation);
00460                         (*it)->Node->getPath(nodePath);
00461 
00462                         char out[2048];
00463                         NLMISC::smprintf(out, 2048, format.c_str(), nodePath.c_str(), statsInline.c_str());
00464                         log->displayRawNL(out);
00465                 }
00466         }
00467         benchClock.stop();
00468         _CurrNode->SonsPreambule += benchClock.getNumTicks();
00469 }

void NLMISC::CHTimer::displayHierarchical CLog log = InfoLog,
bool  displayEx = true,
uint  labelNumChar = 32,
uint  indentationStep = 2
[static]
 

Hierarchical display, no sorting is done

Parameters:
displayEx true to display more detailed infos.
labelNumChar 

Definition at line 472 of file hierarchical_timer.cpp.

References _BenchStartedOnce, _CurrNode, _MsPerTick, _Name, _Parent, _RootNode, _RootTimer, _Sons, _WantStandardDeviation, NLMISC::CHTimer::CStats::buildFromNode(), NLMISC::CHTimer::CStats::buildFromNodes(), depth, NLMISC::CLog::displayNL(), NLMISC::CLog::displayRawNL(), NLMISC::CSimpleClock::getNumTicks(), NLMISC::CHTimer::CStats::getStats(), min, nlassert, NLMISC::CHTimer::CNode::Owner, sint, NLMISC::CHTimer::CNode::Sons, NLMISC::CHTimer::CNode::SonsPreambule, NLMISC::CSimpleClock::start(), NLMISC::CSimpleClock::stop(), TNodeVect, NLMISC::CHTimer::CStats::TotalTime, and uint.

Referenced by NLSOUND::CSoundDriverDSound::displayBench().

00473 {
00474         CSimpleClock    benchClock;
00475         benchClock.start();
00476         log->displayNL("HTIMER: =========================================================================");
00477         log->displayRawNL("HTIMER: Hierarchical display of bench");
00478         nlassert(_BenchStartedOnce); // should have done at least one bench
00479         typedef std::map<CHTimer *, TNodeVect> TNodeMap;
00480         TNodeMap nodeMap;
00481         TNodeVect nodeLeft;     
00482         nodeLeft.push_back(&_RootNode);
00484         while (!nodeLeft.empty())
00485         {       
00486                 CNode *currNode = nodeLeft.back();
00487                 nodeMap[currNode->Owner].push_back(currNode);
00488                 nodeLeft.pop_back();
00489                 nodeLeft.insert(nodeLeft.end(), currNode->Sons.begin(), currNode->Sons.end());
00490 
00491         }
00492         log->displayRawNL("HTIMER: %*s |      total |      local |       visits |  loc%%/ glb%% |       min |       max |      mean", labelNumChar, "");
00493 
00495         CStats  rootStats;
00496         rootStats.buildFromNode(&_RootNode, _MsPerTick);
00497 
00499         CStats  currNodeStats;
00500         std::vector<uint> sonsIndex;
00501         uint depth = 0;
00502         CHTimer *currTimer = &_RootTimer;
00503         sonsIndex.push_back(0);
00504         bool displayStat = true;
00505         std::string resultName;
00506         std::string resultStats;
00507         while (!sonsIndex.empty())
00508         {               
00509                 if (displayStat)
00510                 {
00511                         resultName.resize(labelNumChar);
00512                         std::fill(resultName.begin(), resultName.end(), '.');
00513                         uint startIndex = depth * indentationStep;
00514                         uint endIndex = std::min(startIndex + (uint)::strlen(currTimer->_Name), labelNumChar);                  
00515                         if ((sint) (endIndex - startIndex) >= 1)
00516                         {
00517                                 std::copy(currTimer->_Name, currTimer->_Name + (endIndex - startIndex), resultName.begin() + startIndex);
00518                         }
00519                         TNodeVect &execNodes = nodeMap[currTimer];
00520                         if (execNodes.size() > 0)
00521                         {
00522                                 currNodeStats.buildFromNodes(&execNodes[0], execNodes.size(), _MsPerTick);                      
00523                                 currNodeStats.getStats(resultStats, displayEx, rootStats.TotalTime, _WantStandardDeviation);
00524                                 log->displayRawNL("HTIMER: %s", (resultName + resultStats).c_str());
00525                         }
00526                 }
00527                 if (sonsIndex.back() == currTimer->_Sons.size())
00528                 {
00529                         sonsIndex.pop_back();
00530                         currTimer = currTimer->_Parent;
00531                         displayStat = false;
00532                         -- depth;
00533                 }
00534                 else
00535                 {
00536                         currTimer = currTimer->_Sons[sonsIndex.back()];
00537                         ++ sonsIndex.back();
00538                         sonsIndex.push_back(0);                 
00539                         displayStat = true;
00540                         ++ depth;
00541                 }
00542         }       
00543         benchClock.stop();
00544         _CurrNode->SonsPreambule += benchClock.getNumTicks();
00545 }

void NLMISC::CHTimer::displayHierarchicalByExecutionPath CLog log = InfoLog,
bool  displayEx = true,
uint  labelNumChar = 32,
uint  indentationStep = 2
[static]
 

Hierarchical display, no sorting is done

Parameters:
displayEx true to display more detailed infos.
labelNumChar 

Definition at line 549 of file hierarchical_timer.cpp.

References displayHierarchicalByExecutionPathSorted(), NoSort, and uint.

00550 {
00551         displayHierarchicalByExecutionPathSorted(log, NoSort, displayEx, labelNumChar, indentationStep);
00552 }

void NLMISC::CHTimer::displayHierarchicalByExecutionPathSorted CLog log = InfoLog,
TSortCriterion  criterion = TotalTime,
bool  displayEx = true,
uint  labelNumChar = 32,
uint  indentationStep = 2
[static]
 

Hierarchical display, sorting is done in branchs

Parameters:
displayEx true to display more detailed infos.
labelNumChar 

Definition at line 556 of file hierarchical_timer.cpp.

References _BenchStartedOnce, _CurrNode, _MsPerTick, _Name, _RootNode, _WantStandardDeviation, NLMISC::CHTimer::CStats::buildFromNode(), NLMISC::CHTimer::CStatSorter::Criterion, NLMISC::CLog::displayRawNL(), NLMISC::CSimpleClock::getNumTicks(), NLMISC::CHTimer::CStats::getStats(), min, nlassert, NoSort, NLMISC::CHTimer::CNode::Owner, sint, NLMISC::CHTimer::CNode::Sons, NLMISC::CHTimer::CNode::SonsPreambule, NLMISC::CSimpleClock::start(), NLMISC::CSimpleClock::stop(), NLMISC::CHTimer::CStats::TotalTime, and uint.

Referenced by NLSOUND::CSoundDriverDSound::displayBench(), and displayHierarchicalByExecutionPath().

00557 {
00558 
00559         CSimpleClock    benchClock;
00560         benchClock.start();
00561         nlassert(_BenchStartedOnce); // should have done at least one bench
00562 
00563         // get root total time.
00564         CStats  rootStats;
00565         rootStats.buildFromNode(&_RootNode, _MsPerTick);
00566 
00567 
00568         // display header.
00569         CLog::TDisplayInfo      dummyDspInfo;
00570         log->displayRawNL("HTIMER: =========================================================================");
00571         log->displayRawNL("HTIMER: Hierarchical display of bench by execution path");
00572         log->displayRawNL("HTIMER: %*s |      total |      local |       visits |  loc%%/ glb%% |       min |       max |      mean", labelNumChar, "");
00573 
00574 
00575         // use list because vector of vector is bad.
00576         std::list< CExamStackEntry >    examStack;
00577 
00578         // Add the root to the stack.
00579         examStack.push_back( CExamStackEntry( &_RootNode ) );
00580         CStats          currNodeStats;
00581         std::string resultName;
00582         std::string resultStats;
00583 
00584         while (!examStack.empty())
00585         {
00586                 CNode                           *node = examStack.back().Node;
00587                 std::vector<CNode*>     &children= examStack.back().Children;
00588                 uint                            child = examStack.back().CurrentChild;
00589 
00590                 // If child 0, then must first build children info and display me.
00591                 if (child == 0)
00592                 {
00593                         // Build Sons Infos.
00594                         // ==============
00595                         
00596                         // resize array
00597                         children.resize(node->Sons.size());
00598 
00599                         // If no sort, easy.
00600                         if(criterion == NoSort)
00601                         {
00602                                 children= node->Sons;
00603                         }
00604                         // else, Sort them with criterion.
00605                         else
00606                         {
00607                                 std::vector<CNodeStat>          stats;
00608                                 std::vector<CNodeStat *>        ptrStats;
00609                                 stats.resize(children.size());
00610                                 ptrStats.resize(children.size());
00611 
00612                                 // build stats.
00613                                 uint    i;
00614                                 for(i=0; i<children.size(); i++)
00615                                 {
00616                                         CNode   *childNode= node->Sons[i];
00617                                         stats[i].buildFromNode(childNode, _MsPerTick);
00618                                         stats[i].Node = childNode;
00619                                         ptrStats[i]= &stats[i];
00620                                 }
00621 
00622                                 // sort.
00623                                 CStatSorter     sorter;
00624                                 sorter.Criterion= criterion;
00625                                 std::sort(ptrStats.begin(), ptrStats.end(), sorter);            
00626 
00627                                 // fill children.
00628                                 for(i=0; i<children.size(); i++)
00629                                 {
00630                                         children[i]= ptrStats[i]->Node;
00631                                 }
00632                         }
00633 
00634 
00635                         // Display our infos
00636                         // ==============
00637                         // build the indented node name.
00638                         resultName.resize(labelNumChar);
00639                         std::fill(resultName.begin(), resultName.end(), '.');
00640                         uint startIndex = (examStack.size()-1) * indentationStep;
00641                         uint endIndex = std::min(startIndex + (uint)::strlen(node->Owner->_Name), labelNumChar);                        
00642                         if ((sint) (endIndex - startIndex) >= 1)
00643                         {
00644                                 std::copy(node->Owner->_Name, node->Owner->_Name + (endIndex - startIndex), resultName.begin() + startIndex);
00645                         }
00646 
00647                         // build the stats string.
00648                         currNodeStats.buildFromNode(node, _MsPerTick);                  
00649                         currNodeStats.getStats(resultStats, displayEx, rootStats.TotalTime, _WantStandardDeviation);
00650 
00651                         // display
00652                         log->displayRawNL("HTIMER: %s", (resultName + resultStats).c_str());
00653                 }
00654 
00655                 // End of sons?? stop.
00656                 if (child >= children.size())
00657                 {
00658                         examStack.pop_back();
00659                         continue;
00660                 }
00661 
00662                 // next son.
00663                 ++(examStack.back().CurrentChild);
00664 
00665                 // process the current son.
00666                 examStack.push_back( CExamStackEntry( children[child] ) );
00667         }
00668 
00669         //
00670         benchClock.stop();
00671         _CurrNode->SonsPreambule += benchClock.getNumTicks();
00672 }

void NLMISC::CHTimer::displaySummary CLog log = InfoLog,
TSortCriterion  criterion = TotalTime,
bool  displayEx = true,
uint  labelNumChar = 32,
uint  indentationStep = 2,
uint  maxDepth = 3
[static]
 

Hierarchical display, sorting is done in branchs

Parameters:
displayEx true to display more detailed infos.
labelNumChar 

Definition at line 675 of file hierarchical_timer.cpp.

References _BenchStartedOnce, _CurrNode, _MsPerTick, _Name, _RootNode, _WantStandardDeviation, NLMISC::CHTimer::CStats::buildFromNode(), NLMISC::CHTimer::CStatSorter::Criterion, depth, NLMISC::CLog::displayRawNL(), NLMISC::CSimpleClock::getNumTicks(), NLMISC::CHTimer::CStats::getStats(), min, nlassert, NoSort, NLMISC::CHTimer::CNode::Owner, sint, NLMISC::CHTimer::CNode::Sons, NLMISC::CHTimer::CNode::SonsPreambule, NLMISC::CSimpleClock::start(), NLMISC::CSimpleClock::stop(), NLMISC::CHTimer::CStats::TotalTime, and uint.

00676 {
00677 
00678         CSimpleClock    benchClock;
00679         benchClock.start();
00680         nlassert(_BenchStartedOnce); // should have done at least one bench
00681 
00682         // get root total time.
00683         CStats  rootStats;
00684         rootStats.buildFromNode(&_RootNode, _MsPerTick);
00685 
00686 
00687         // display header.
00688         CLog::TDisplayInfo      dummyDspInfo;
00689         log->displayRawNL("HTIMER: =========================================================================");
00690         log->displayRawNL("HTIMER: Hierarchical display of bench by execution path");
00691         log->displayRawNL("HTIMER: %*s |      total |      local |       visits |  loc%%/ glb%% |       min |       max |      mean", labelNumChar, "");
00692 
00693 
00694         // use list because vector of vector is bad.
00695         std::list< CExamStackEntry >    examStack;
00696 
00697         // Add the root to the stack.
00698         examStack.push_back( CExamStackEntry( &_RootNode ) );
00699         CStats          currNodeStats;
00700         std::string resultName;
00701         std::string resultStats;
00702 
00703         while (!examStack.empty())
00704         {
00705                 CNode                           *node = examStack.back().Node;
00706                 std::vector<CNode*>     &children= examStack.back().Children;
00707                 uint                            child = examStack.back().CurrentChild;
00708                 uint                            depth = examStack.back().Depth;
00709 
00710                 // If child 0, then must first build children info and display me.
00711                 if (child == 0)
00712                 {
00713                         // Build Sons Infos.
00714                         // ==============
00715                         
00716                         // resize array
00717                         children.resize(node->Sons.size());
00718 
00719                         // If no sort, easy.
00720                         if(criterion == NoSort)
00721                         {
00722                                 children= node->Sons;
00723                         }
00724                         // else, Sort them with criterion.
00725                         else
00726                         {
00727                                 std::vector<CNodeStat>          stats;
00728                                 std::vector<CNodeStat *>        ptrStats;
00729                                 stats.resize(children.size());
00730                                 ptrStats.resize(children.size());
00731 
00732                                 // build stats.
00733                                 uint    i;
00734                                 for(i=0; i<children.size(); i++)
00735                                 {
00736                                         CNode   *childNode= node->Sons[i];
00737                                         stats[i].buildFromNode(childNode, _MsPerTick);
00738                                         stats[i].Node = childNode;
00739                                         ptrStats[i]= &stats[i];
00740                                 }
00741 
00742                                 // sort.
00743                                 CStatSorter     sorter;
00744                                 sorter.Criterion= criterion;
00745                                 std::sort(ptrStats.begin(), ptrStats.end(), sorter);            
00746 
00747                                 // fill children.
00748                                 for(i=0; i<children.size(); i++)
00749                                 {
00750                                         children[i]= ptrStats[i]->Node;
00751                                 }
00752                         }
00753 
00754 
00755                         // Display our infos
00756                         // ==============
00757                         // build the indented node name.
00758                         resultName.resize(labelNumChar);
00759                         std::fill(resultName.begin(), resultName.end(), '.');
00760                         uint startIndex = (examStack.size()-1) * indentationStep;
00761                         uint endIndex = std::min(startIndex + (uint)::strlen(node->Owner->_Name), labelNumChar);                        
00762                         if ((sint) (endIndex - startIndex) >= 1)
00763                         {
00764                                 std::copy(node->Owner->_Name, node->Owner->_Name + (endIndex - startIndex), resultName.begin() + startIndex);
00765                         }
00766 
00767                         // build the stats string.
00768                         currNodeStats.buildFromNode(node, _MsPerTick);                  
00769                         currNodeStats.getStats(resultStats, displayEx, rootStats.TotalTime, _WantStandardDeviation);
00770 
00771                         // display
00772                         log->displayRawNL("HTIMER: %s", (resultName + resultStats).c_str());
00773                 }
00774 
00775                 // End of sons?? stop.
00776                 if (child >= children.size())
00777                 {
00778                         examStack.pop_back();
00779                         continue;
00780                 }
00781 
00782                 // next son.
00783                 ++(examStack.back().CurrentChild);
00784 
00785                 // process the current son.
00786                 if (depth+1 < maxDepth)
00787                         examStack.push_back( CExamStackEntry( children[child], depth+1 ) );
00788         }
00789 
00790         //
00791         benchClock.stop();
00792         _CurrNode->SonsPreambule += benchClock.getNumTicks();
00793 }

void NLMISC::CHTimer::doAfter bool  displayAfter = false  )  [private]
 

Definition at line 957 of file hierarchical_timer.cpp.

References _AfterStopEstimateTime, _CurrNode, _CurrTimer, _MsPerTick, _PreambuleClock, _WantStandardDeviation, NLMISC::CHTimer::CNode::Clock, NLMISC::CSimpleClock::getNumTicks(), NLMISC::CHTimer::CNode::LastSonsTotalTime, NLMISC::CHTimer::CNode::MaxTime, NLMISC::CHTimer::CNode::Measures, min, NLMISC::CHTimer::CNode::MinTime, nlinfo, NLMISC::CHTimer::CNode::NumVisits, NLMISC::CHTimer::CNode::Parent, sint64, NLMISC::CHTimer::CNode::SonsPreambule, NLMISC::CHTimer::CNode::SonsTotalTime, NLMISC::CSimpleClock::start(), NLMISC::CSimpleClock::stop(), NLMISC::CHTimer::CNode::TotalTime, and uint64.

Referenced by after().

00958 {
00959         _CurrNode->Clock.stop();                
00960         _PreambuleClock.start();
00961         /* Remove my Son preambule, and remove only ONE StartStop
00962                 It is because between the start and the end, only ONE rdtsc time is counted:
00963         */
00964         sint64 numTicks = _CurrNode->Clock.getNumTicks()  - _CurrNode->SonsPreambule - (CSimpleClock::getStartStopNumTicks());
00965         // Case where the SonPreambule is overestimated, 
00966         numTicks= std::max((sint64)0, numTicks);
00967         // In case where the SonPreambule is overestimated, the TotalTime must not be < of the SonTime
00968         if(_CurrNode->TotalTime + numTicks < _CurrNode->SonsTotalTime)
00969                 numTicks= _CurrNode->SonsTotalTime - _CurrNode->TotalTime;
00970         
00971         _CurrNode->TotalTime += numTicks;
00972         _CurrNode->MinTime = std::min(_CurrNode->MinTime, (uint64)numTicks);
00973         _CurrNode->MaxTime = std::max(_CurrNode->MaxTime, (uint64)numTicks);
00974         _CurrNode->LastSonsTotalTime = _CurrNode->SonsTotalTime;
00975 
00976         if (displayAfter)
00977         {               
00978                 nlinfo("HTIMER: %s %.3fms loop number %d", _Name, numTicks * _MsPerTick, _CurrNode->NumVisits);
00979         }
00980         //
00981         if (_WantStandardDeviation)
00982         {
00983                 _CurrNode->Measures.push_back(numTicks * _MsPerTick);
00984         }
00985         //
00986         if (_Parent)
00987         {
00988                 _CurrTimer = _Parent;
00989         }       
00990         //
00991         if (_CurrNode->Parent)
00992         {
00993                 CNode   *curNode= _CurrNode;
00994                 CNode   *parent= _CurrNode->Parent;
00995                 parent->SonsTotalTime += numTicks;
00996                 _PreambuleClock.stop();
00997                 /*
00998                         The SonPreambule of my parent is 
00999                                 + my BeforePreambule (counted in doBefore)
01000                                 + my Afterpreambule (see below)
01001                                 + my Sons Preambule 
01002                                 + some constant time due to the Start/Stop of the _CurrNode->Clock, the 2* Start/Stop
01003                                         of the PreabmuleClock, the function call time of doBefore and doAfter
01004                 */
01005                 parent->SonsPreambule += _PreambuleClock.getNumTicks() + curNode->SonsPreambule + _AfterStopEstimateTime;
01006                 // walk to parent
01007                 _CurrNode= parent;
01008         }
01009         else
01010         {
01011                 _PreambuleClock.stop();
01012         }
01013 }

void NLMISC::CHTimer::doBefore  )  [private]
 

Definition at line 935 of file hierarchical_timer.cpp.

References _CurrNode, _CurrTimer, _PreambuleClock, _Sons, NLMISC::CHTimer::CNode::Clock, NLMISC::CSimpleClock::getNumTicks(), NLMISC::CHTimer::CNode::NumVisits, NLMISC::CHTimer::CNode::Parent, NLMISC::CHTimer::CNode::SonsPreambule, NLMISC::CSimpleClock::start(), NLMISC::CSimpleClock::stop(), and walkTreeToCurrent().

Referenced by before().

00936 {       
00937         _PreambuleClock.start();        
00938         walkTreeToCurrent();                    
00939         ++ _CurrNode->NumVisits;
00940         _CurrNode->SonsPreambule = 0;
00941         if (!_Parent && _CurrTimer != this)
00942         {
00943                 _Parent = _CurrTimer;
00944                 // register as a son of the parent
00945                 _Parent->_Sons.push_back(this); 
00946         }
00947         _CurrTimer = this;
00948         _PreambuleClock.stop();
00949         if (_CurrNode->Parent)
00950         {       
00951                 _CurrNode->Parent->SonsPreambule += _PreambuleClock.getNumTicks();
00952         }
00953         _CurrNode->Clock.start();
00954 }

void NLMISC::CHTimer::endBench  )  [static]
 

Ends a bench session.

Definition at line 271 of file hierarchical_timer.cpp.

References _Benching, _CurrNode, _RootNode, _RootTimer, after(), and nlwarning.

Referenced by NLSOUND::CSoundDriverDSound::endBench().

00272 {
00273         if (!_Benching)
00274                 return;
00275 
00276         if (_CurrNode == &_RootNode)
00277         {
00278                 _RootTimer.after();
00279         }
00280         else
00281         {
00282                 nlwarning("HTIMER: Stopping the bench inside a benched functions !");
00283         }
00284         _Benching = false;
00285 }

void NLMISC::CHTimer::estimateAfterStopTime  )  [static, private]
 

Definition at line 194 of file hierarchical_timer.cpp.

References _AfterStopEstimateTime, _AfterStopEstimateTimeDone, _Benching, _BenchStartedOnce, _MsPerTick, _RootNode, _RootTimer, _WantStandardDeviation, after(), before(), clear(), NLMISC::CHTimer::CNode::Owner, NLMISC::CHTimer::CNode::SonsTotalTime, NLMISC::CHTimer::CNode::TotalTime, and uint.

Referenced by startBench().

00195 {
00196         if(_AfterStopEstimateTimeDone)
00197                 return;
00198         const uint numSamples = 1000;
00199 
00200         // Do as in startBench, reset and init
00201         clear();
00202         
00203         {
00204 #ifdef NL_CPU_INTEL
00205                 double freq = (double) CSystemInfo::getProcessorFrequency(false);
00206                 _MsPerTick = 1000 / (double) freq;
00207 #else
00208                 _MsPerTick = CTime::ticksToSecond(1000);
00209 #endif
00210                 CSimpleClock::init();
00211         }
00212         
00213         // start
00214         _Benching = true;
00215         _BenchStartedOnce = true;
00216         _RootNode.Owner = &_RootTimer;
00217         _WantStandardDeviation = false;
00218         _RootTimer.before();
00219         
00220         for(uint i=0;i<numSamples;i++)
00221         {
00222                 static NLMISC::CHTimer          estimateSampleTimer("sampleTimer");
00223                 estimateSampleTimer.before();
00224                 estimateSampleTimer.after();
00225         }
00226 
00227         _RootTimer.after();
00228         _Benching = false;
00229 
00230         // Then the After Stop time is the rootTimer time / numSamples
00231         _AfterStopEstimateTime= (_RootNode.TotalTime-_RootNode.SonsTotalTime) / numSamples;
00232 
00233         _AfterStopEstimateTimeDone= true;
00234 
00235         // must re-clear.
00236         clear();
00237 }

const char* NLMISC::CHTimer::getName void   )  const [inline]
 

Definition at line 222 of file hierarchical_timer.h.

Referenced by NLMISC::CHTimer::CNode::getPath().

00222 { return _Name; }

void NLMISC::CHTimer::setName const char *  name  )  [inline]
 

Definition at line 223 of file hierarchical_timer.h.

00223 { _Name = name; }

void NLMISC::CHTimer::startBench bool  wantStandardDeviation = false,
bool  quick = false,
bool  reset = true
[static]
 

Starts a bench session

Parameters:
wantStandardDeviation When true, benchs will report the standard deviation of values. This require more memory, however, because each samples must be kept.
quick if true, quick compute the frequency of the processor

Definition at line 241 of file hierarchical_timer.cpp.

References _Benching, _BenchStartedOnce, _MsPerTick, _RootNode, _RootTimer, _WantStandardDeviation, before(), clear(), estimateAfterStopTime(), nlassert, and NLMISC::CHTimer::CNode::Owner.

Referenced by bench(), and NLSOUND::CSoundDriverDSound::startBench().

00242 {
00243         nlassert(!_Benching);
00244 
00245         // if not done, estimate the AfterStopTime
00246         estimateAfterStopTime();
00247         
00248         if(reset)
00249                 clear();
00250 
00251         if(reset)
00252         {
00253 #ifdef NL_CPU_INTEL
00254                 double freq = (double) CSystemInfo::getProcessorFrequency(quick);
00255                 _MsPerTick = 1000 / (double) freq;
00256 #else
00257                 _MsPerTick = CTime::ticksToSecond(1000);
00258 #endif
00259                 CSimpleClock::init();
00260         }
00261 
00262         // Launch
00263         _Benching = true;
00264         _BenchStartedOnce = true;
00265         _RootNode.Owner = &_RootTimer;
00266         _WantStandardDeviation = wantStandardDeviation;
00267         _RootTimer.before();
00268 }

void NLMISC::CHTimer::walkTreeToCurrent  )  [private]
 

Definition at line 169 of file hierarchical_timer.cpp.

References _CurrNode, _IsRoot, NLMISC::CHTimer::CNode::Sons, and uint.

Referenced by doBefore().

00170 {
00171         if (_IsRoot) return;    
00172         bool found = false;
00173         for(uint k = 0; k < _CurrNode->Sons.size(); ++k)
00174         {
00175                 if (_CurrNode->Sons[k]->Owner == this)
00176                 {
00177                         _CurrNode = _CurrNode->Sons[k];
00178                         found = true;
00179                         break;
00180                 }
00181         }
00182         if (!found)
00183         {
00184                 // no node for this execution path : create a new one
00185                 _CurrNode->Sons.push_back(new CNode(this, _CurrNode));
00186                 _CurrNode->Sons.back()->Parent = _CurrNode;
00187                 _CurrNode = _CurrNode->Sons.back();
00188         }
00189 }


Field Documentation

sint64 NLMISC::CHTimer::_AfterStopEstimateTime = 0 [static, private]
 

Definition at line 57 of file hierarchical_timer.cpp.

Referenced by doAfter(), and estimateAfterStopTime().

bool NLMISC::CHTimer::_AfterStopEstimateTimeDone = false [static, private]
 

Definition at line 58 of file hierarchical_timer.cpp.

Referenced by estimateAfterStopTime().

bool NLMISC::CHTimer::_Benching = false [static, private]
 

Definition at line 52 of file hierarchical_timer.cpp.

Referenced by after(), before(), benching(), endBench(), estimateAfterStopTime(), and startBench().

bool NLMISC::CHTimer::_BenchStartedOnce = false [static, private]
 

Definition at line 53 of file hierarchical_timer.cpp.

Referenced by display(), displayByExecutionPath(), displayHierarchical(), displayHierarchicalByExecutionPathSorted(), displaySummary(), estimateAfterStopTime(), and startBench().

CHTimer::CNode * NLMISC::CHTimer::_CurrNode = &_RootNode [static, private]
 

Definition at line 49 of file hierarchical_timer.cpp.

Referenced by clear(), display(), displayByExecutionPath(), displayHierarchical(), displayHierarchicalByExecutionPathSorted(), displaySummary(), doAfter(), doBefore(), endBench(), and walkTreeToCurrent().

CHTimer * NLMISC::CHTimer::_CurrTimer = &_RootTimer [static, private]
 

Definition at line 56 of file hierarchical_timer.cpp.

Referenced by doAfter(), and doBefore().

bool NLMISC::CHTimer::_IsRoot [private]
 

Definition at line 430 of file hierarchical_timer.h.

Referenced by CHTimer(), and walkTreeToCurrent().

double NLMISC::CHTimer::_MsPerTick [static, private]
 

Definition at line 54 of file hierarchical_timer.cpp.

Referenced by display(), displayByExecutionPath(), displayHierarchical(), displayHierarchicalByExecutionPathSorted(), displaySummary(), doAfter(), estimateAfterStopTime(), and startBench().

const char* NLMISC::CHTimer::_Name [private]
 

Definition at line 424 of file hierarchical_timer.h.

Referenced by displayHierarchical(), displayHierarchicalByExecutionPathSorted(), and displaySummary().

CHTimer* NLMISC::CHTimer::_Parent [private]
 

Definition at line 426 of file hierarchical_timer.h.

Referenced by displayHierarchical().

CSimpleClock NLMISC::CHTimer::_PreambuleClock [static, private]
 

This clock is used to measure the preambule of methods such as CHTimer::before() This is static, but the Hierarchical Timer doesn't support multithreading anyway..

Definition at line 50 of file hierarchical_timer.cpp.

Referenced by doAfter(), and doBefore().

CHTimer::CNode NLMISC::CHTimer::_RootNode [static, private]
 

Definition at line 48 of file hierarchical_timer.cpp.

Referenced by clear(), display(), displayByExecutionPath(), displayHierarchical(), displayHierarchicalByExecutionPathSorted(), displaySummary(), endBench(), estimateAfterStopTime(), and startBench().

CHTimer NLMISC::CHTimer::_RootTimer [static, private]
 

Referenced by displayHierarchical(), endBench(), estimateAfterStopTime(), and startBench().

TTimerVect NLMISC::CHTimer::_Sons [private]
 

Definition at line 428 of file hierarchical_timer.h.

Referenced by displayHierarchical(), and doBefore().

bool NLMISC::CHTimer::_WantStandardDeviation = false [static, private]
 

Definition at line 55 of file hierarchical_timer.cpp.

Referenced by display(), displayByExecutionPath(), displayHierarchical(), displayHierarchicalByExecutionPathSorted(), displaySummary(), doAfter(), estimateAfterStopTime(), and startBench().


The documentation for this class was generated from the following files:
Generated on Tue Mar 16 13:17:26 2004 for NeL by doxygen 1.3.6