home *** CD-ROM | disk | FTP | other *** search
/ GameStar 2006 March / Gamestar_82_2006-03_dvd.iso / DVDStar / Editace / quake4_sdkv10.exe / source / idlib / TimingCollection.cpp < prev    next >
C/C++ Source or Header  |  2005-11-14  |  10KB  |  399 lines

  1.  
  2. #include "precompiled.h"
  3. #pragma hdrstop
  4.  
  5. #if !defined(__TIMINGCOLLECTION_H_)
  6.     #include "TimingCollection.h"
  7. #endif
  8.  
  9. #ifdef RV_TIMERCOLLECTION
  10.  
  11. //-----------------------------------------------------------------------------
  12. //
  13. //                                rvSingleTiming::Clear
  14. //
  15. //-----------------------------------------------------------------------------
  16.  
  17. void rvSingleTiming::Clear( void )
  18. {
  19.     mTotalUpdates            = 0;
  20.     mCurValue                = 0;
  21.     mTotalValue                = 0;
  22.     mPeakValue                = 0;
  23.     mLimit                    = 0;
  24.     mLimitExceeded            = 0;
  25.     mLimitExceededTimesFive    = 0;
  26.     mDisplayLevel            = 0;
  27.     mName                    = "";
  28.     mParentName                = "";
  29.  
  30.     mStartFile                = "";
  31.     mStartLine                = 0;
  32.     mEndFile                = "";
  33.     mEndLine                = 0;
  34. }
  35.  
  36. //-----------------------------------------------------------------------------
  37. //
  38. //                                rvSingleTiming::rvSingleTiming
  39. //
  40. //-----------------------------------------------------------------------------
  41.  
  42. rvSingleTiming::rvSingleTiming()
  43. {
  44.     Clear();
  45. }
  46.  
  47. //-----------------------------------------------------------------------------
  48. //
  49. //                                rvSingleTiming::rvSingleTiming
  50. //
  51. //-----------------------------------------------------------------------------
  52.  
  53. rvSingleTiming::rvSingleTiming( idStr &newName )
  54. {
  55.     Clear();
  56.     mName = newName;
  57. }
  58.  
  59. //-----------------------------------------------------------------------------
  60. //
  61. //                                rvSingleTiming::OutputDataToFile
  62. //
  63. //-----------------------------------------------------------------------------
  64.  
  65. void rvSingleTiming::OutputDataToFile( idFile *file, int framesRecorded )
  66. {
  67.     char    buffer[1024];
  68.     idStr    outputName = "";
  69.  
  70.     for( int i = 0; i < mDisplayLevel; i++ )
  71.     {
  72.         outputName += "**";
  73.     }
  74.     outputName += mName;
  75.  
  76.     sprintf(buffer, "%-36s %-9.3f %-9.3f %-9.3f %-9.3f %-9i %-9i %-9.3f\n", outputName.c_str(), 
  77.         (float)mTotalValue, (float)( mTotalValue / (float)framesRecorded), (float)mPeakValue,
  78.         (float)mLimit, mLimitExceeded, mLimitExceededTimesFive, (float)(mTotalUpdates / (float)framesRecorded) );
  79.     file->Write ( buffer, strlen( buffer ) );
  80. }
  81.  
  82. //-----------------------------------------------------------------------------
  83. //
  84. //                                rvSingleTiming::OutputInfoToFile
  85. //
  86. //-----------------------------------------------------------------------------
  87.  
  88. void rvSingleTiming::OutputInfoToFile( idFile *file )
  89. {
  90.     char    buffer[1024];
  91.  
  92.     sprintf(buffer, "Name: %s\nParent: %s\n", mName.c_str(), mParentName.c_str() );
  93.     file->Write ( buffer, strlen( buffer ) );
  94.  
  95.     sprintf(buffer, "Starting at %s(%d)\nEnding at %s(%d)\n\n", mStartFile.c_str(), mStartLine, mEndFile.c_str(), mEndLine );
  96.     file->Write ( buffer, strlen( buffer ) );
  97. }
  98.  
  99.  
  100.  
  101.  
  102.  
  103.  
  104.  
  105.  
  106.  
  107.  
  108.  
  109.  
  110.  
  111.  
  112. //-----------------------------------------------------------------------------
  113. //
  114. //                                rvTimingCollection::Clear
  115. //
  116. //-----------------------------------------------------------------------------
  117.  
  118. void rvTimingCollection::Clear( void )
  119. {
  120.     mUpdates            = 0;
  121.     mCurTimer            = 0;
  122.     mFramesRecorded        = 0;
  123.     mCurrentlyUpdating    = 0;
  124.     mTimings.Clear();
  125.     mTimingsIndex.Clear();
  126. }
  127.  
  128. //-----------------------------------------------------------------------------
  129. //
  130. //                                rvTimingCollection::rvTimingCollection
  131. //
  132. //-----------------------------------------------------------------------------
  133.  
  134. rvTimingCollection::rvTimingCollection()
  135. {
  136.     Clear();
  137. }
  138.  
  139. //-----------------------------------------------------------------------------
  140. //
  141. //                                rvTimingCollection::GetTiming
  142. //
  143. //-----------------------------------------------------------------------------
  144.  
  145. rvSingleTiming *rvTimingCollection::GetTiming( idStr &timingName )
  146. {
  147.     int *handle = NULL;
  148.  
  149.     if( mTimingsIndex.Get( timingName, &handle ) ) 
  150.     {    
  151.         return( &mTimings[*handle] );
  152.     }
  153.  
  154.     rvSingleTiming    newTiming( timingName );
  155.     int                index = mTimings.Num();
  156.     
  157.     mTimingsIndex.Set( timingName, index );
  158.     mTimings.Append( newTiming );
  159.     return &mTimings[index];
  160. }
  161.  
  162. //-----------------------------------------------------------------------------
  163. //
  164. //                                rvTimingCollection::DisplayTimingValues
  165. //
  166. //-----------------------------------------------------------------------------
  167.  
  168. void rvTimingCollection::DisplayTimingValues( void ) {
  169.     // Fixme: the display resulting from this is really, really a mess - quite unreadable.
  170.     common->Printf ( "Timer: \n" );
  171.     for( int i = 0; i < mTimings.Num(); i++ ) {
  172.         if ( (int)(mTimings[i].mCurValue) ) {
  173.             common->Printf( "\t%s %3i\n", mTimings[i].mName.c_str(), (int)(mTimings[i].mCurValue) );
  174.         }
  175.     }
  176. }
  177.  
  178. //-----------------------------------------------------------------------------
  179. //
  180. //                                rvTimingCollection::OutputToFile
  181. //
  182. //-----------------------------------------------------------------------------
  183.  
  184. void rvTimingCollection::OutputToFile( void )
  185. {
  186.     idFile    *file    = NULL;
  187.     idStr    name;
  188.     char    buffer[1024];
  189.  
  190.     // Fixme: Do we have any good information for building a better file name here?
  191.  
  192.     name = "Timings/output.txt";
  193.  
  194.     file = fileSystem->OpenFileWrite ( name );
  195.     if ( !file )
  196.     {
  197.         return;
  198.     }
  199.  
  200.     sprintf( buffer, "Total frames = %d\n\n", mFramesRecorded );
  201.     file->Write( buffer, strlen( buffer ) );
  202.  
  203.     sprintf( buffer, "%-36s %-9s %-9s %-9s %-9s %-9s %-9s %-9s\n\n",
  204.         "Name", "Total", "Average", "Peak", "Limit", "Exceeded", "Exceed*5", "Calls" );
  205.     file->Write ( buffer, strlen( buffer ) );
  206.  
  207.     for( int i = 0; i < mTimings.Num(); i++ )
  208.     {
  209.         mTimings[i].OutputDataToFile( file, mFramesRecorded );
  210.         if( !( ( i + 1 )%3) )    // break up the prints into groups of 3 to make scanning visually easier.
  211.         {
  212.             sprintf( buffer, "\n" );
  213.             file->Write( buffer, strlen( buffer ) );
  214.         }
  215.     }
  216.  
  217.     sprintf(buffer, "\n\nInformation about categories\n\n" );
  218.     file->Write ( buffer, strlen( buffer ) );
  219.  
  220.     for( int i = 0; i < mTimings.Num(); i++ )
  221.     {
  222.         mTimings[i].OutputInfoToFile( file );
  223.     }
  224.  
  225.     fileSystem->CloseFile ( file );
  226.     file = NULL;
  227. }
  228.  
  229. //-----------------------------------------------------------------------------
  230. //
  231. //                                rvTimingCollection::AppendToDict
  232. //
  233. //-----------------------------------------------------------------------------
  234.  
  235. void rvTimingCollection::AppendToDict( idDict *dict )
  236. {
  237.     if( !mCurrentlyUpdating )
  238.     {
  239.         return;
  240.     }
  241.  
  242.     for( int i = 0; i < mTimings.Num(); i++ )
  243.     {
  244.         dict->Set ( mTimings[i].mName.c_str(), va( "%0.3g\t%0.3g\t", mTimings[i].mCurValue, mTimings[i].mTotalValue ) );
  245.     }
  246. }
  247.  
  248. //-----------------------------------------------------------------------------
  249. //
  250. //                                rvTimingCollection::InitFrame
  251. //
  252. //-----------------------------------------------------------------------------
  253.  
  254. void rvTimingCollection::InitFrame( bool inUse, bool displayText, bool outputFileWhenDone )
  255. {
  256.     // Do our quick reject test to ensure this is quick when not in use.
  257.  
  258.     if( !inUse )
  259.     {
  260.         if( mCurrentlyUpdating )
  261.         {
  262.             if( outputFileWhenDone )
  263.             {
  264.                 OutputToFile();
  265.             }
  266.             mCurrentlyUpdating = 0;
  267.         }
  268.         return;
  269.     }
  270.  
  271.     mCurrentlyUpdating = 1;
  272.     mUpdates++;
  273.     mFramesRecorded++;
  274.  
  275.     if( mUpdates >= 10 && displayText )
  276.     {
  277.         // ??  If we display output every single frame, we get REALLY bogged down.  It is bad.
  278.  
  279.         DisplayTimingValues();
  280.  
  281.         mUpdates = 0;
  282.  
  283.         return;
  284.     }
  285.  
  286.     // Clear only the curValues and record information.
  287.  
  288.     for( int i = 0; i < mTimings.Num(); i++ )
  289.     {
  290.         if( mTimings[i].mCurValue > mTimings[i].mPeakValue )
  291.         {
  292.             mTimings[i].mPeakValue = mTimings[i].mCurValue;
  293.         }
  294.  
  295.         if( mTimings[i].mLimit > 0.0 && mTimings[i].mCurValue > mTimings[i].mLimit )
  296.         {
  297.             mTimings[i].mLimitExceeded++;
  298.         }
  299.  
  300.         if( mTimings[i].mLimit > 0.0 && mTimings[i].mCurValue > mTimings[i].mLimit * 5 )
  301.         {
  302.             mTimings[i].mLimitExceededTimesFive++;
  303.         }
  304.  
  305.         mTimings[i].mCurValue = 0.0f;
  306.     }
  307. }
  308.  
  309. //-----------------------------------------------------------------------------
  310. //
  311. //                                rvTimingCollection::TimingStart
  312. //
  313. //-----------------------------------------------------------------------------
  314.  
  315. void rvTimingCollection::_TimingStart( const char *timingName, const char *fileName, const int lineNum )
  316. {
  317.     // Do our quick reject test to ensure this is quick when not in use.
  318.  
  319.     if( !mCurrentlyUpdating )
  320.     {
  321.         return;
  322.     }
  323.  
  324.     // Go up the timer list.
  325.  
  326.     mCurTimer++; 
  327.     assert( mCurTimer < MAX_TIMERS );
  328.  
  329.     // Keep track of the current function being timed in case we nest and need to know our parent.
  330.  
  331.     mTimerName[mCurTimer] = timingName;
  332.  
  333.     // Set the information about this timer.
  334.  
  335.     rvSingleTiming *curTiming = GetTiming( mTimerName[mCurTimer] );
  336.     
  337.     if( mCurTimer == 0 )
  338.     {
  339.         curTiming->mParentName = "base";
  340.     }
  341.     else
  342.     {
  343.         curTiming->mParentName = mTimerName[mCurTimer - 1];
  344.     }
  345.     curTiming->mStartFile        = fileName;
  346.     curTiming->mStartLine        = lineNum;
  347.     curTiming->mDisplayLevel    = mCurTimer - 1;
  348.  
  349.     // Start the timer; do it last to avoid timing the rest of this function.
  350.  
  351.     mTimer[mCurTimer].Clear();
  352.     mTimer[mCurTimer].Start();
  353. }
  354.  
  355. //-----------------------------------------------------------------------------
  356. //
  357. //                                rvTimingCollection::TimingEnd
  358. //
  359. //-----------------------------------------------------------------------------
  360.  
  361. void rvTimingCollection::_TimingStop( double msecLimit, const char *fileName, const int lineNum )
  362. {
  363.     // Do our quick reject test to ensure this is quick when not in use.
  364.  
  365.     if( !mCurrentlyUpdating )
  366.     {
  367.         return;
  368.     }
  369.  
  370.     // Stop our timer first so that we don't log time from the rest of this function.
  371.  
  372.     mTimer[mCurTimer].Stop();
  373.  
  374.     // Update incidental information on the timer.
  375.  
  376.     rvSingleTiming *curTiming = GetTiming( mTimerName[mCurTimer] );
  377.     
  378.     curTiming->mEndFile = fileName;
  379.     curTiming->mEndLine = lineNum;
  380.  
  381.     curTiming->mLimit    = msecLimit;
  382.  
  383.     // Add the actual timing values to the rvSingleTiming
  384.  
  385.     double    frameTime = mTimer[mCurTimer].Milliseconds();
  386.  
  387.     curTiming->mCurValue    += frameTime;
  388.     curTiming->mTotalValue    += frameTime;
  389.  
  390.     curTiming->mTotalUpdates++;
  391.  
  392.     // Go back down the timer list.
  393.  
  394.     mCurTimer--;
  395.     assert( mCurTimer >= 0 );
  396. }
  397.  
  398. #endif
  399.