| # Gaudi Framework, version v20r2
Generated: 18 Jul 2008

- Main Page
- Namespaces
- Classes
- Files
- Directories
- Related Pages

- Search for |

- File List
- File Members

# ChronoStatSvc.cpp

Go to the documentation of this file.

    00001 // $Id: ChronoStatSvc.cpp,v 1.18 2008/05/13 12:37:19 marcocle Exp $
    00002 // ============================================================================
    00003 // CVS tag $Name: v17r1 $, version $Revision: 1.18 $
    00004 // ============================================================================
    00005 #ifdef _WIN32
    00006 #pragma warning( disable : 4786 )
    00007 #endif
    00008 // ============================================================================
    00009 // STD & STL
    00010 // ============================================================================
    00011 #include <iostream>
    00012 #include <iomanip>
    00013 #include <string>
    00014 #include <algorithm>
    00015 #include <functional>
    00016 #include <fstream>
    00017 #include <iomanip>
    00018 // ============================================================================
    00019 // GaudiKernel
    00020 // ============================================================================
    00021 #include "GaudiKernel/Kernel.h"
    00022 #include "GaudiKernel/StatusCode.h"
    00023 #include "GaudiKernel/SvcFactory.h"
    00024 #include "GaudiKernel/IChronoStatSvc.h"
    00025 #include "GaudiKernel/MsgStream.h"
    00026 #include "GaudiKernel/ChronoEntity.h"
    00027 #include "GaudiKernel/StatEntity.h"
    00028 #include "GaudiKernel/Stat.h"
    00029 // ============================================================================
    00031 // ============================================================================
    00032 #include "ChronoStatSvc.h"
    00033 // ============================================================================
    00036 // ============================================================================
    00037 DECLARE_SERVICE_FACTORY(ChronoStatSvc)
    00038 // ============================================================================
    00045 // ============================================================================
    00046 // ============================================================================
    00047 //  comparison functor
    00048 // ============================================================================
    00049 class ComparePairOfChronoEntityAndChronoTag
    00050   : public std::binary_function<
    00051   const std::pair<ChronoEntity*,const IChronoStatSvc::ChronoTag*> ,
    00052   const std::pair<ChronoEntity*,const IChronoStatSvc::ChronoTag*> , bool >
    00053 {
    00054 public:
    00055   inline bool operator()
    00056     ( const  std::pair<ChronoEntity*,
    00057       const IChronoStatSvc::ChronoTag*>& p1 ,
    00058       const  std::pair< ChronoEntity*,
    00059       const IChronoStatSvc::ChronoTag*>& p2 ) const
    00060   {
    00061     const ChronoEntity* e1 = p1.first;
    00062     const ChronoEntity* e2 = p2.first;
    00063     return ( ( 0 == e1 || 0 == e2 ) ? true : (*e1)<(*e2) ) ;
    00064   }
    00065 };
    00066 // ============================================================================
    00067 //  comparison functor
    00068 // ============================================================================
    00069 class ComparePairOfStatEntityAndStatTag
    00070   : public std::binary_function<
    00071   const std::pair<const StatEntity*,const IChronoStatSvc::StatTag*> ,
    00072   const std::pair<const StatEntity*,const IChronoStatSvc::StatTag*> , bool >
    00073 {
    00074 public:
    00076   inline bool operator()
    00077     ( const std::pair<const StatEntity*,
    00078       const IChronoStatSvc::StatTag*>& p1,
    00079       const std::pair<const StatEntity*,
    00080       const IChronoStatSvc::StatTag*>& p2 ) const
    00081   {
    00082     const StatEntity* se1 = p1.first;
    00083     const StatEntity* se2 = p2.first;
    00084     return ( 0 == se1 || 0 == se2 ) ? true : (*se1)<(*se2) ;
    00085   }
    00086 };
    00087 // ============================================================================
    00088 // Constructor
    00089 // ============================================================================
    00090 ChronoStatSvc::ChronoStatSvc
    00091 ( const std::string& name, ISvcLocator* svcloc )
    00092   : Service( name , svcloc )
    00093   , m_chronoEntities   ()
    00094   , m_chronoPrintLevel ( MSG::INFO )
    00095   , m_statEntities     ()
    00096   , m_statPrintLevel   ( MSG::INFO )
    00097   //
    00098   // the header row
    00099   , m_header  ( "     Counter     |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |")
    00100   // format for regular statistical printout rows
    00101   , m_format1 ( " %|-15.15s|%|17t||%|10d| |%|11.7g| |%|#11.5g| |%|#11.5g| |%|#12.5g| |%|#12.5g| |" )
    00102   // format for "efficiency" statistical printout rows
    00103   , m_format2 ( "*%|-15.15s|%|17t||%|10d| |%|11.5g| |(%|#9.7g| +- %|-#9.7g|)%%|   -------   |   -------   |" )
    00104   // flag to use the special "efficiency" format
    00105   , m_useEffFormat ( true )
    00106 {
    00108   declareProperty ( "ChronoPrintOutTable"    ,
    00109                     m_chronoTableFlag      = true      );
    00111   declareProperty ( "ChronoDestinationCout"  ,
    00112                     m_chronoCoutFlag       = false     );
    00114   declareProperty ( "ChronoPrintLevel"       ,
    00115                     m_intChronoPrintLevel  = MSG::INFO );
    00118   declareProperty ( "ChronoTableToBeOrdered" ,
    00119                     m_chronoOrderFlag      = true      );
    00121   declareProperty ( "PrintUserTime"          ,
    00122                     m_printUserTime        = true      );
    00124   declareProperty ( "PrintSystemTime"        ,
    00125                     m_printSystemTime      = false     );
    00127   declareProperty ( "PrintEllapsedTime"      ,
    00128                     m_printEllapsedTime    = false     );
    00131   declareProperty ( "StatPrintOutTable"      ,
    00132                     m_statTableFlag        = true      );
    00134   declareProperty ( "StatDestinationCout"    ,
    00135                     m_statCoutFlag         = false     );
    00137   declareProperty ( "StatPrintLevel"         ,
    00138                     m_intStatPrintLevel    = MSG::INFO );
    00141   declareProperty ( "StatTableToBeOrdered"   ,
    00142                     m_statOrderFlag        = true      );
    00143
    00144   // specify the number of events to be skipped by the memory auditor
    00145   // in order to better spot memory leak
    00146   declareProperty ( "NumberOfSkippedEventsForMemStat"      ,
    00147                     m_numberOfSkippedEventsForMemStat = -1 ) ;
    00148
    00149   declareProperty( "AsciiStatsOutputFile",
    00150                    m_statsOutFileName = "",
    00151                    "Name of the output file storing the stats. If empty, no"
    00152                    " statistics will be saved (default)" );
    00153
    00154   declareProperty
    00155     ( "StatTableHeader"        , m_header                          ,
    00156       "The header row for the output Stat-table"                   ) ;
    00157   declareProperty
    00158     ( "RegularRowFormat"       , m_format1                         ,
    00159       "The format for the regular row in the output Stat-table"    ) ;
    00160   declareProperty
    00161     ( "EfficiencyRowFormat"    , m_format2                         ,
    00162       "The format for the regular row in the outptu Stat-table"    ) ;
    00163   declareProperty
    00164     ( "UseEfficiencyRowFormat" , m_useEffFormat                    ,
    00165       "Use the special format for printout of efficiency counters" ) ;
    00166 }
    00167 // ============================================================================
    00168 // Destructor.
    00169 // ============================================================================
    00170 ChronoStatSvc::~ChronoStatSvc()
    00171 {
    00172   // clear the container of chrono entities
    00173   m_chronoEntities.clear();
    00174   // clear the container of stat   entities
    00175   m_statEntities.clear();
    00176 }
    00177 // ============================================================================
    00178 // Implementation of IService::initialize()
    00179 // ============================================================================
    00180 StatusCode ChronoStatSvc::initialize()
    00181 {
    00182   StatusCode sc = Service::initialize();
    00183   if ( sc.isFailure() ) return sc;
    00185   MsgStream log( msgSvc() , this->name() );
    00186
    00187   // Set my own properties
    00188   sc = setProperties();
    00189
    00190   if (sc.isFailure()) {
    00191     log << MSG::ERROR << "setting my properties" << endreq;
    00192     return StatusCode::FAILURE;
    00193   }
    00194
    00195   log << MSG::INFO << " Number of skipped events for MemStat"
    00196       << m_numberOfSkippedEventsForMemStat << endreq ;
    00197
    00201   m_statPrintLevel =
    00202     ( MSG::FATAL < m_intStatPrintLevel   ) ? MSG::FATAL :
    00203     ( MSG::NIL   > m_intStatPrintLevel   ) ? MSG::NIL   :
    00204     ( MSG::Level ) m_intStatPrintLevel  ;
    00206   m_chronoPrintLevel =
    00207     ( MSG::FATAL < m_intChronoPrintLevel ) ? MSG::FATAL :
    00208     ( MSG::NIL   > m_intChronoPrintLevel ) ? MSG::NIL   :
    00209     ( MSG::Level ) m_intChronoPrintLevel ;
    00211   if( m_chronoTableFlag  &&
    00212       !m_printUserTime   &&
    00213       !m_printSystemTime &&
    00214       !m_printEllapsedTime ) { m_printUserTime   = true ; }
    00216   if(  m_printUserTime    ||
    00217        m_printSystemTime  ||
    00218        m_printEllapsedTime ) { m_chronoTableFlag = true ; }
    00221   chronoStart( name() ) ;
    00223   return StatusCode::SUCCESS;
    00224 }
    00225 // ============================================================================
    00226 // Implementation of IService::finalize()
    00227 // ============================================================================
    00228 StatusCode ChronoStatSvc::finalize()
    00229 {
    00230   std::string local = name()+".finalize()";
    00232   MsgStream log( msgSvc() , local );
    00235   chronoStop( name() ) ;
    00236
    00239   if ( m_chronoTableFlag &&
    00240        !m_chronoEntities.empty() &&
    00241        ( m_printUserTime || m_printSystemTime ) )
    00242     {
    00244       MsgStream log( msgSvc() , "*****Chrono*****" );
    00245       const std::string stars( ( m_chronoCoutFlag ) ? 126 : 100  , '*' );
    00246       if( m_chronoCoutFlag  )
    00247         {
    00248           std::cout << stars << std::endl;
    00249           std::cout << local <<  " The Final CPU consumption (Chrono) Table "
    00250                     << ( m_chronoOrderFlag ? "(ordered)" : "(not ordered)" ) << std::endl;
    00251           std::cout << stars << std::endl;
    00252         }
    00253       else
    00254         {
    00255           log << (MSG::Level) m_chronoPrintLevel
    00256         << stars << endreq;
    00257           log << (MSG::Level) m_chronoPrintLevel
    00258         << " The Final CPU consumption ( Chrono ) Table "
    00259               << ( m_chronoOrderFlag ? "(ordered)" : "(not ordered)" ) << endreq;
    00260           log << (MSG::Level) m_chronoPrintLevel << stars << endreq;
    00261         }
    00263       {  // prepare container for printing
    00264         typedef std::pair<ChronoEntity*,const ChronoTag*>        MPair;
    00265         typedef std::vector<MPair>                               MCont;
    00266         MCont tmpCont;
    00267         for( ChronoMap::iterator it = m_chronoEntities.begin() ;
    00268        m_chronoEntities.end() != it ;  ++it )
    00269           { tmpCont.push_back( MPair( &(it->second) , &(it->first) ) ) ; }
    00270         // sort it
    00271         if( m_chronoOrderFlag )
    00272   { std::sort( tmpCont.begin() ,
    00273                tmpCont.end()   ,
    00274                ComparePairOfChronoEntityAndChronoTag() ); }
    00275         // print User Time statistics
    00276         if( m_printUserTime   )
    00277           {
    00278             for( MCont::iterator iter = tmpCont.begin() ;  tmpCont.end() != iter ; ++iter )
    00279               {
    00280                 //
    00281                 ChronoEntity*    entity = iter->first  ; if( 0 == entity ) { continue ; }
    00282                 const ChronoTag* tag    = iter->second ; if( 0 == tag    ) { continue ; }
    00283
    00284                 entity->stop();
    00285
    00286                 if     ( m_chronoCoutFlag )
    00287                   { std::cout << *tag << "\t"  << entity->outputUserTime  () << std::endl ; }
    00288                 else
    00289                   {
    00290                     MsgStream log( msgSvc() , *tag ) ;
    00291                     log << m_chronoPrintLevel << entity->outputUserTime  () << endreq ;
    00292                   }
    00293                 //
    00294               }
    00295           }
    00297         if( m_printSystemTime )
    00298           {
    00301             if      ( m_printUserTime && m_chronoCoutFlag   )
    00302               { std::cout << stars << std::endl;                           }
    00303             else if ( m_printUserTime && !m_chronoCoutFlag  )
    00304               { log << (MSG::Level) m_chronoPrintLevel << stars << endreq; }
    00306             for( MCont::iterator iter = tmpCont.begin() ;  tmpCont.end() != iter ; ++iter )
    00307               {
    00309                 ChronoEntity*    entity = iter->first  ; if( 0 == entity ) { continue ; }
    00310                 const ChronoTag* tag    = iter->second ; if( 0 == tag    ) { continue ; }
    00311
    00312                 entity->stop();
    00313
    00314                 if     ( m_chronoCoutFlag )
    00315                   { std::cout << *tag << "\t"  << entity->outputSystemTime() << std::endl ; }
    00316                 else
    00317                   {
    00318                     MsgStream log( msgSvc() , *tag ) ;
    00319                     log << m_chronoPrintLevel << entity->outputSystemTime() << endreq ;
    00320                   }
    00321                 //
    00322               }
    00323           }
    00325         if( m_printEllapsedTime )
    00326           {
    00329             if      ( ( m_printUserTime || m_printSystemTime ) &&  m_chronoCoutFlag  )
    00330               { std::cout << stars << std::endl;                           }
    00331             else if ( ( m_printUserTime || m_printSystemTime ) && !m_chronoCoutFlag  )
    00332               { log << (MSG::Level) m_chronoPrintLevel << stars << endreq; }
    00334             for( MCont::iterator iter = tmpCont.begin() ;  tmpCont.end() != iter ; ++iter )
    00335               {
    00337                 ChronoEntity*    entity = iter->first  ; if( 0 == entity ) { continue ; }
    00338                 const ChronoTag* tag    = iter->second ; if( 0 == tag    ) { continue ; }
    00339
    00340                 entity->stop();
    00341
    00342                 if     ( m_chronoCoutFlag )
    00343                   { std::cout << *tag << "\t"  << entity->outputElapsedTime() << std::endl ; }
    00344                 else
    00345                   {
    00346                     MsgStream log( msgSvc() , *tag ) ;
    00347                     log << m_chronoPrintLevel << entity->outputElapsedTime() << endreq ;
    00348                   }
    00349                 //
    00350               }
    00351           }
    00353         tmpCont.clear();
    00354       }
    00356       if( m_chronoCoutFlag  ) { std::cout << stars << std::endl;              }
    00357       else                    { log << m_chronoPrintLevel << stars << endreq; }
    00358     }
    00359
    00361
    00363   if ( m_statTableFlag ) { printStats () ; }
    00364
    00365   if ( !m_statsOutFileName.value().empty() ) {
    00366     saveStats();
    00367   }
    00368
    00369   log << MSG::INFO << " Service finalized succesfully " << endreq;
    00370
    00371   return Service::finalize();
    00372 }
    00373 // ============================================================================
    00374 // Implementation of IInterface::queryInterface()
    00375 // ============================================================================
    00376 StatusCode
    00377 ChronoStatSvc::queryInterface
    00378 ( const InterfaceID& riid ,
    00379   void** ppvInterface    )
    00380 {
    00381   if ( 0 == ppvInterface ) { return StatusCode::FAILURE ; }
    00382   else if ( IChronoSvc::interfaceID()     == riid )
    00383   { *ppvInterface = static_cast<IChronoSvc*>     (this) ; }
    00384   else if ( IStatSvc::interfaceID()       == riid )
    00385   { *ppvInterface = static_cast<IStatSvc*>       (this) ; }
    00386   else if ( IChronoStatSvc::interfaceID() == riid )
    00387   { *ppvInterface = static_cast<IChronoStatSvc*> (this) ; }
    00388   else { return Service::queryInterface(riid, ppvInterface) ; }
    00389   addRef();
    00390   return StatusCode::SUCCESS;
    00391 }
    00392 // ============================================================================
    00393 // Implementation of IChronoStatSvc::chronoStart
    00394 // ============================================================================
    00395 ChronoEntity*
    00396 ChronoStatSvc::chronoStart
    00397 ( const ChronoTag& chronoTag )
    00398 {
    00399   ChronoEntity& entity = m_chronoEntities [ chronoTag ] ;
    00400   entity.start() ;
    00401   return &entity ;
    00402 }
    00403 // ============================================================================
    00404 // Implementation of IChronoStatSvc::chronoStop
    00405 // ============================================================================
    00406 const ChronoEntity*
    00407 ChronoStatSvc::chronoStop
    00408 ( const IChronoStatSvc::ChronoTag& chronoTag )
    00409 {
    00410   ChronoEntity& entity = m_chronoEntities [ chronoTag ] ;
    00411   entity.stop() ;
    00412   return &entity ;
    00413 }
    00414 // ============================================================================
    00415 // Implementation of IChronoStatSvc::chronoDelta
    00416 // ============================================================================
    00417 IChronoStatSvc::ChronoTime
    00418 ChronoStatSvc::chronoDelta
    00419 ( const IChronoStatSvc::ChronoTag& chronoTag,
    00420   IChronoStatSvc::ChronoType theType )
    00421 {
    00422   return m_chronoEntities[ chronoTag ].delta( theType );
    00423 }
    00424 // ============================================================================
    00425 // Implementation of IChronoStatSvc::chronoPrint
    00426 // ============================================================================
    00427 void    ChronoStatSvc::chronoPrint
    00428 ( const IChronoStatSvc::ChronoTag& chronoTag )
    00429 {
    00430   MsgStream log ( msgSvc() , chronoTag );
    00431   if( m_printUserTime   ) {
    00432     log << (MSG::Level) m_chronoPrintLevel
    00433         << m_chronoEntities[ chronoTag ].outputUserTime  ()
    00434         << endreq;
    00435   }
    00436   if( m_printSystemTime ) {
    00437     log << (MSG::Level) m_chronoPrintLevel
    00438         << m_chronoEntities[ chronoTag ].outputSystemTime()
    00439         << endreq;
    00440   }
    00441 }
    00442 // ============================================================================
    00443 // Implementation of IChronoSvc::chronoStatus
    00444 // ============================================================================
    00445 IChronoStatSvc::ChronoStatus
    00446 ChronoStatSvc::chronoStatus
    00447 ( const IChronoStatSvc::ChronoTag& chronoTag )
    00448 { return m_chronoEntities[ chronoTag ].status(); }
    00449 // ============================================================================
    00450 // Implementation of IChronoStatSvc::stat
    00451 // ============================================================================
    00452 void    ChronoStatSvc::stat
    00453 ( const IChronoStatSvc::StatTag    & statTag    ,
    00454   const IChronoStatSvc::StatFlag   & statFlag   )
    00455 {
    00456   StatMap::iterator theIter=m_statEntities.find(statTag);
    00457
    00458   StatEntity * theStat=0 ;
    00459   // if new entity, specify the neumber of events to be skipped
    00460   if (theIter==m_statEntities.end()){
    00461     // new stat entity
    00462     StatEntity& theSe = m_statEntities[ statTag ];
    00463     theStat=& theSe;
    00464     theStat->setnEntriesBeforeReset(m_numberOfSkippedEventsForMemStat);
    00465   }
    00466   else
    00467   {
    00468     //existing stat entity
    00469     theStat=&((*theIter).second);
    00470   }
    00471
    00472   theStat->addFlag ( statFlag ) ;
    00473 }
    00474 // ============================================================================
    00475 // Implementation of IChronoStatSvc::statPrint
    00476 // ============================================================================
    00477 void    ChronoStatSvc::statPrint
    00478 ( const IChronoStatSvc::StatTag& statTag )
    00479 {
    00480   MsgStream log ( msgSvc() , statTag ) ;
    00481   log << (MSG::Level) m_statPrintLevel << m_statEntities[ statTag ] << endreq;
    00482 }
    00483 // ============================================================================
    00484 /*  extract the chrono entity for the given tag (name)
    00485  *  @see IChronoStatSvc
    00486  *  @param t chrono tag(name)
    00487  *  @return pointer to chrono entity
    00488  */
    00489 // ============================================================================
    00490 const ChronoEntity* ChronoStatSvc::chrono
    00491 ( const IChronoStatSvc::ChronoTag& t ) const
    00492 {
    00493   ChronoMap::const_iterator it = m_chronoEntities.find ( t ) ;
    00494   if ( m_chronoEntities.end() != it ) { return &(it->second) ; }
    00495   return 0 ;
    00496 }
    00497 // ============================================================================
    00498 /*  extract the stat   entity for the given tag (name)
    00499  *  @see IChronoStatSvc
    00500  *  @param t stat   tag(name)
    00501  *  @return pointer to stat   entity
    00502  */
    00503 // ============================================================================
    00504 const StatEntity*   ChronoStatSvc::stat
    00505 ( const IChronoStatSvc::StatTag&   t ) const
    00506 {
    00507   StatMap::const_iterator it = m_statEntities.find ( t ) ;
    00508   if ( m_statEntities.end() != it ) { return &(it->second) ; }
    00509   return 0 ;
    00510 }
    00511 // ============================================================================
    00512 // dump all the statistics into an ASCII file
    00513 // ============================================================================
    00514 void ChronoStatSvc::saveStats()
    00515 {
    00516   std::ofstream out( m_statsOutFileName.value().c_str(),
    00517                      std::ios_base::out | std::ios_base::trunc );
    00518   if ( !out.good() ) {
    00519     MsgStream msg( msgSvc() , name() );
    00520     msg << MSG::INFO
    00521         << "Could not open the output file for writing chrono statistics ["
    00522         << m_statsOutFileName.value() << "]"
    00523         << endreq;
    00524     return;
    00525   } else {
    00526     // format it our way
    00527     out << std::scientific << std::setprecision(8) ;
    00528   }
    00529
    00530   // ChronoEntity
    00531   typedef std::pair<ChronoEntity*, const ChronoTag*> MPair;
    00532   typedef std::vector<MPair>                         MCont;
    00533   MCont chronos;
    00534
    00535   for( ChronoMap::iterator it = m_chronoEntities.begin() ;
    00536        m_chronoEntities.end() != it ;  ++it ) {
    00537     chronos.push_back( MPair( &(it->second) , &(it->first) ) ) ;
    00538   }
    00539
    00540   // sort it
    00541   std::sort( chronos.begin() ,
    00542              chronos.end()   ,
    00543              ComparePairOfChronoEntityAndChronoTag() );
    00544
    00545   // print User Time statistics
    00546   for( MCont::iterator iter = chronos.begin() ;
    00547        chronos.end() != iter;
    00548        ++iter ) {
    00549     //
    00550     const ChronoEntity*    entity = iter->first;
    00551     if( 0 == entity ) { continue ; }
    00552
    00553     const ChronoTag* tag    = iter->second ;
    00554     if( 0 == tag    ) { continue ; }
    00555
    00556     // create an entry in the .INI-like table
    00557     out << "\n[" << *tag << "]\n";
    00558
    00559     // user
    00560     out << "cpu_user_total = " << entity->uTotalTime() << "\n";
    00561     out << "cpu_user_min = "   << entity->uMinimalTime() << "\n";
    00562     out << "cpu_user_mean = "  << entity->uMeanTime() << "\n";
    00563     out << "cpu_user_RMS = "   << entity->uRMSTime() << "\n";
    00564     out << "cpu_user_max = "   << entity->uMaximalTime() << "\n";
    00565     out << "cpu_user_nbr = "   << entity->nOfMeasurements() << "\n";
    00566
    00567     // system
    00568     out << "\n"; // just for clarity
    00569     out << "cpu_system_total = " << entity->kTotalTime() << "\n";
    00570     out << "cpu_system_min = "   << entity->kMinimalTime() << "\n";
    00571     out << "cpu_system_mean = "  << entity->kMeanTime() << "\n";
    00572     out << "cpu_system_RMS = "   << entity->kRMSTime() << "\n";
    00573     out << "cpu_system_max = "   << entity->kMaximalTime() << "\n";
    00574     out << "cpu_system_nbr = "   << entity->nOfMeasurements() << "\n";
    00575
    00576     // real
    00577     out << "\n"; // just for clarity
    00578     out << "cpu_real_total = " << entity->eTotalTime() << "\n";
    00579     out << "cpu_real_min = "   << entity->eMinimalTime() << "\n";
    00580     out << "cpu_real_mean = "  << entity->eMeanTime() << "\n";
    00581     out << "cpu_real_RMS = "   << entity->eRMSTime() << "\n";
    00582     out << "cpu_real_max = "   << entity->eMaximalTime() << "\n";
    00583     out << "cpu_real_nbr = "   << entity->nOfMeasurements() << "\n";
    00584
    00585   }
    00586
    00587   out << std::endl;
    00588 }
    00589 // ============================================================================
    00590 // print the "Stat" part of the ChronoStatSvc
    00591 // ============================================================================
    00592 void ChronoStatSvc::printStats()
    00593 {
    00595   if ( m_statEntities.empty() ) { return ; }
    00596
    00597   MsgStream log ( msgSvc() , "******Stat******" ) ;
    00599   const std::string stars( ( m_statCoutFlag ) ? 126 : 100  , '*' ) ;
    00601   if ( m_statCoutFlag  )
    00602         {
    00603           std::cout << stars << std::endl;
    00604           std::cout <<  " The Final stat Table "
    00605               << ( m_statOrderFlag ? "(ordered)" : "(not ordered)" ) << std::endl;
    00606           std::cout << stars << std::endl;
    00607         }
    00608   else
    00609   {
    00610           log << m_statPrintLevel << stars << endreq;
    00611           log <<  m_statPrintLevel << " The Final stat Table "
    00612               << ( m_statOrderFlag ? "(ordered)" : "(not ordered)" ) << endreq;
    00613           log << m_statPrintLevel << stars << endreq;
    00614         }
    00615
    00616   {
    00617     // prepare container for printing
    00618     typedef std::pair<const StatEntity*,const StatTag*>  SPair;
    00619     typedef std::vector<SPair>                           SCont;
    00620     SCont tmpCont;
    00621     for( StatMap::const_iterator it = m_statEntities.begin();
    00622          it != m_statEntities.end(); it++ )
    00623     { tmpCont.push_back( SPair( &(it->second) , &(it->first) ) ) ; }
    00624     // sort it
    00625     if ( m_statOrderFlag )
    00626     { std::sort( tmpCont.begin() ,
    00627                  tmpCont.end()   ,
    00628                  ComparePairOfStatEntityAndStatTag() ); }
    00629
    00630
    00631     {
    00632       // print the table header
    00633       if ( m_statCoutFlag ) { std::cout <<                     m_header << std::endl ; }
    00634       else                  { log       << m_statPrintLevel << m_header << endreq    ; }
    00635     }
    00636     // loop over counters and print them:
    00637     for ( SCont::iterator iter = tmpCont.begin() ; tmpCont.end() != iter ; ++iter )
    00638           {
    00640       const StatEntity* entity = iter->first  ;
    00641       if ( 0 == entity ) { continue ; }
    00642       const StatTag*    tag    = iter->second ;
    00643       if ( 0 == tag    ) { continue ; }
    00644
    00645             if ( m_statCoutFlag )
    00646       {
    00647         std::cout
    00648           << Gaudi::Utils::formatAsTableRow
    00649           ( *tag , *entity , m_useEffFormat , m_format1 , m_format2 )
    00650           << std::endl;
    00651       }
    00652             else
    00653       {
    00654         log
    00655           << m_statPrintLevel
    00656           << Gaudi::Utils::formatAsTableRow
    00657           ( *tag , *entity , m_useEffFormat , m_format1 , m_format2 )
    00658           << endreq ;
    00659       }
    00660           }
    00661     tmpCont.clear();
    00662   }
    00664   if ( m_statCoutFlag  ) { std::cout << stars << std::endl;            }
    00665   else                   { log << m_statPrintLevel << stars << endreq; }
    00666 }
    00667
    00668 // ============================================================================
    00669 // The END
    00670 // ============================================================================