| # Gaudi Framework, version v21r6 |

Home |  | Generated: 11 Nov 2009

# 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:  $, 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   : base_class( 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" << endmsg;
    00192     return StatusCode::FAILURE;
    00193   }
    00194
    00195   log << MSG::INFO << " Number of skipped events for MemStat"
    00196       << m_numberOfSkippedEventsForMemStat << endmsg ;
    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 << endmsg;
    00257           log << (MSG::Level) m_chronoPrintLevel
    00258         << " The Final CPU consumption ( Chrono ) Table "
    00259               << ( m_chronoOrderFlag ? "(ordered)" : "(not ordered)" ) << endmsg;
    00260           log << (MSG::Level) m_chronoPrintLevel << stars << endmsg;
    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  () << endmsg ;
    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 << endmsg; }
    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() << endmsg ;
    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 << endmsg; }
    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() << endmsg ;
    00348                   }
    00349                 //
    00350               }
    00351           }
    00353         tmpCont.clear();
    00354       }
    00356       if( m_chronoCoutFlag  ) { std::cout << stars << std::endl;              }
    00357       else                    { log << m_chronoPrintLevel << stars << endmsg; }
    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 successfully " << endmsg;
    00370
    00371   return Service::finalize();
    00372 }
    00373 // ============================================================================
    00374 // Implementation of IChronoStatSvc::chronoStart
    00375 // ============================================================================
    00376 ChronoEntity*
    00377 ChronoStatSvc::chronoStart
    00378 ( const ChronoTag& chronoTag )
    00379 {
    00380   ChronoEntity& entity = m_chronoEntities [ chronoTag ] ;
    00381   entity.start() ;
    00382   return &entity ;
    00383 }
    00384 // ============================================================================
    00385 // Implementation of IChronoStatSvc::chronoStop
    00386 // ============================================================================
    00387 const ChronoEntity*
    00388 ChronoStatSvc::chronoStop
    00389 ( const IChronoStatSvc::ChronoTag& chronoTag )
    00390 {
    00391   ChronoEntity& entity = m_chronoEntities [ chronoTag ] ;
    00392   entity.stop() ;
    00393   return &entity ;
    00394 }
    00395 // ============================================================================
    00396 // Implementation of IChronoStatSvc::chronoDelta
    00397 // ============================================================================
    00398 IChronoStatSvc::ChronoTime
    00399 ChronoStatSvc::chronoDelta
    00400 ( const IChronoStatSvc::ChronoTag& chronoTag,
    00401   IChronoStatSvc::ChronoType theType )
    00402 {
    00403   return m_chronoEntities[ chronoTag ].delta( theType );
    00404 }
    00405 // ============================================================================
    00406 // Implementation of IChronoStatSvc::chronoPrint
    00407 // ============================================================================
    00408 void    ChronoStatSvc::chronoPrint
    00409 ( const IChronoStatSvc::ChronoTag& chronoTag )
    00410 {
    00411   MsgStream log ( msgSvc() , chronoTag );
    00412   if( m_printUserTime   ) {
    00413     log << (MSG::Level) m_chronoPrintLevel
    00414         << m_chronoEntities[ chronoTag ].outputUserTime  ()
    00415         << endmsg;
    00416   }
    00417   if( m_printSystemTime ) {
    00418     log << (MSG::Level) m_chronoPrintLevel
    00419         << m_chronoEntities[ chronoTag ].outputSystemTime()
    00420         << endmsg;
    00421   }
    00422 }
    00423 // ============================================================================
    00424 // Implementation of IChronoSvc::chronoStatus
    00425 // ============================================================================
    00426 IChronoStatSvc::ChronoStatus
    00427 ChronoStatSvc::chronoStatus
    00428 ( const IChronoStatSvc::ChronoTag& chronoTag )
    00429 { return m_chronoEntities[ chronoTag ].status(); }
    00430 // ============================================================================
    00431 // Implementation of IChronoStatSvc::stat
    00432 // ============================================================================
    00433 void    ChronoStatSvc::stat
    00434 ( const IChronoStatSvc::StatTag    & statTag    ,
    00435   const IChronoStatSvc::StatFlag   & statFlag   )
    00436 {
    00437   StatMap::iterator theIter=m_statEntities.find(statTag);
    00438
    00439   StatEntity * theStat=0 ;
    00440   // if new entity, specify the neumber of events to be skipped
    00441   if (theIter==m_statEntities.end()){
    00442     // new stat entity
    00443     StatEntity& theSe = m_statEntities[ statTag ];
    00444     theStat=& theSe;
    00445     theStat->setnEntriesBeforeReset(m_numberOfSkippedEventsForMemStat);
    00446   }
    00447   else
    00448   {
    00449     //existing stat entity
    00450     theStat=&((*theIter).second);
    00451   }
    00452
    00453   theStat->addFlag ( statFlag ) ;
    00454 }
    00455 // ============================================================================
    00456 // Implementation of IChronoStatSvc::statPrint
    00457 // ============================================================================
    00458 void    ChronoStatSvc::statPrint
    00459 ( const IChronoStatSvc::StatTag& statTag )
    00460 {
    00461   MsgStream log ( msgSvc() , statTag ) ;
    00462   log << (MSG::Level) m_statPrintLevel << m_statEntities[ statTag ] << endmsg;
    00463 }
    00464 // ============================================================================
    00465 /*  extract the chrono entity for the given tag (name)
    00466  *  @see IChronoStatSvc
    00467  *  @param t chrono tag(name)
    00468  *  @return pointer to chrono entity
    00469  */
    00470 // ============================================================================
    00471 const ChronoEntity* ChronoStatSvc::chrono
    00472 ( const IChronoStatSvc::ChronoTag& t ) const
    00473 {
    00474   ChronoMap::const_iterator it = m_chronoEntities.find ( t ) ;
    00475   if ( m_chronoEntities.end() != it ) { return &(it->second) ; }
    00476   return 0 ;
    00477 }
    00478 // ============================================================================
    00479 /*  extract the stat   entity for the given tag (name)
    00480  *  @see IChronoStatSvc
    00481  *  @param t stat   tag(name)
    00482  *  @return pointer to stat   entity
    00483  */
    00484 // ============================================================================
    00485 const StatEntity*   ChronoStatSvc::stat
    00486 ( const IChronoStatSvc::StatTag&   t ) const
    00487 {
    00488   StatMap::const_iterator it = m_statEntities.find ( t ) ;
    00489   if ( m_statEntities.end() != it ) { return &(it->second) ; }
    00490   return 0 ;
    00491 }
    00492 // ============================================================================
    00493 // dump all the statistics into an ASCII file
    00494 // ============================================================================
    00495 void ChronoStatSvc::saveStats()
    00496 {
    00497   std::ofstream out( m_statsOutFileName.value().c_str(),
    00498                      std::ios_base::out | std::ios_base::trunc );
    00499   if ( !out.good() ) {
    00500     MsgStream msg( msgSvc() , name() );
    00501     msg << MSG::INFO
    00502         << "Could not open the output file for writing chrono statistics ["
    00503         << m_statsOutFileName.value() << "]"
    00504         << endmsg;
    00505     return;
    00506   } else {
    00507     // format it our way
    00508     out << std::scientific << std::setprecision(8) ;
    00509   }
    00510
    00511   // ChronoEntity
    00512   typedef std::pair<ChronoEntity*, const ChronoTag*> MPair;
    00513   typedef std::vector<MPair>                         MCont;
    00514   MCont chronos;
    00515
    00516   for( ChronoMap::iterator it = m_chronoEntities.begin() ;
    00517        m_chronoEntities.end() != it ;  ++it ) {
    00518     chronos.push_back( MPair( &(it->second) , &(it->first) ) ) ;
    00519   }
    00520
    00521   // sort it
    00522   std::sort( chronos.begin() ,
    00523              chronos.end()   ,
    00524              ComparePairOfChronoEntityAndChronoTag() );
    00525
    00526   // print User Time statistics
    00527   for( MCont::iterator iter = chronos.begin() ;
    00528        chronos.end() != iter;
    00529        ++iter ) {
    00530     //
    00531     const ChronoEntity*    entity = iter->first;
    00532     if( 0 == entity ) { continue ; }
    00533
    00534     const ChronoTag* tag    = iter->second ;
    00535     if( 0 == tag    ) { continue ; }
    00536
    00537     // create an entry in the .INI-like table
    00538     out << "\n[" << *tag << "]\n";
    00539
    00540     // user
    00541     out << "cpu_user_total = " << entity->uTotalTime() << "\n";
    00542     out << "cpu_user_min = "   << entity->uMinimalTime() << "\n";
    00543     out << "cpu_user_mean = "  << entity->uMeanTime() << "\n";
    00544     out << "cpu_user_RMS = "   << entity->uRMSTime() << "\n";
    00545     out << "cpu_user_max = "   << entity->uMaximalTime() << "\n";
    00546     out << "cpu_user_nbr = "   << entity->nOfMeasurements() << "\n";
    00547
    00548     // system
    00549     out << "\n"; // just for clarity
    00550     out << "cpu_system_total = " << entity->kTotalTime() << "\n";
    00551     out << "cpu_system_min = "   << entity->kMinimalTime() << "\n";
    00552     out << "cpu_system_mean = "  << entity->kMeanTime() << "\n";
    00553     out << "cpu_system_RMS = "   << entity->kRMSTime() << "\n";
    00554     out << "cpu_system_max = "   << entity->kMaximalTime() << "\n";
    00555     out << "cpu_system_nbr = "   << entity->nOfMeasurements() << "\n";
    00556
    00557     // real
    00558     out << "\n"; // just for clarity
    00559     out << "cpu_real_total = " << entity->eTotalTime() << "\n";
    00560     out << "cpu_real_min = "   << entity->eMinimalTime() << "\n";
    00561     out << "cpu_real_mean = "  << entity->eMeanTime() << "\n";
    00562     out << "cpu_real_RMS = "   << entity->eRMSTime() << "\n";
    00563     out << "cpu_real_max = "   << entity->eMaximalTime() << "\n";
    00564     out << "cpu_real_nbr = "   << entity->nOfMeasurements() << "\n";
    00565
    00566   }
    00567
    00568   out << std::endl;
    00569 }
    00570 // ============================================================================
    00571 // print the "Stat" part of the ChronoStatSvc
    00572 // ============================================================================
    00573 void ChronoStatSvc::printStats()
    00574 {
    00576   if ( m_statEntities.empty() ) { return ; }
    00577
    00578   MsgStream log ( msgSvc() , "******Stat******" ) ;
    00580   const std::string stars( ( m_statCoutFlag ) ? 126 : 100  , '*' ) ;
    00582   if ( m_statCoutFlag  )
    00583         {
    00584           std::cout << stars << std::endl;
    00585           std::cout <<  " The Final stat Table "
    00586               << ( m_statOrderFlag ? "(ordered)" : "(not ordered)" ) << std::endl;
    00587           std::cout << stars << std::endl;
    00588         }
    00589   else
    00590   {
    00591           log << m_statPrintLevel << stars << endmsg;
    00592           log <<  m_statPrintLevel << " The Final stat Table "
    00593               << ( m_statOrderFlag ? "(ordered)" : "(not ordered)" ) << endmsg;
    00594           log << m_statPrintLevel << stars << endmsg;
    00595         }
    00596
    00597   {
    00598     // prepare container for printing
    00599     typedef std::pair<const StatEntity*,const StatTag*>  SPair;
    00600     typedef std::vector<SPair>                           SCont;
    00601     SCont tmpCont;
    00602     for( StatMap::const_iterator it = m_statEntities.begin();
    00603          it != m_statEntities.end(); it++ )
    00604     { tmpCont.push_back( SPair( &(it->second) , &(it->first) ) ) ; }
    00605     // sort it
    00606     if ( m_statOrderFlag )
    00607     { std::sort( tmpCont.begin() ,
    00608                  tmpCont.end()   ,
    00609                  ComparePairOfStatEntityAndStatTag() ); }
    00610
    00611
    00612     {
    00613       // print the table header
    00614       if ( m_statCoutFlag ) { std::cout <<                     m_header << std::endl ; }
    00615       else                  { log       << m_statPrintLevel << m_header << endmsg    ; }
    00616     }
    00617     // loop over counters and print them:
    00618     for ( SCont::iterator iter = tmpCont.begin() ; tmpCont.end() != iter ; ++iter )
    00619           {
    00621       const StatEntity* entity = iter->first  ;
    00622       if ( 0 == entity ) { continue ; }
    00623       const StatTag*    tag    = iter->second ;
    00624       if ( 0 == tag    ) { continue ; }
    00625
    00626             if ( m_statCoutFlag )
    00627       {
    00628         std::cout
    00629           << Gaudi::Utils::formatAsTableRow
    00630           ( *tag , *entity , m_useEffFormat , m_format1 , m_format2 )
    00631           << std::endl;
    00632       }
    00633             else
    00634       {
    00635         log
    00636           << m_statPrintLevel
    00637           << Gaudi::Utils::formatAsTableRow
    00638           ( *tag , *entity , m_useEffFormat , m_format1 , m_format2 )
    00639           << endmsg ;
    00640       }
    00641           }
    00642     tmpCont.clear();
    00643   }
    00645   if ( m_statCoutFlag  ) { std::cout << stars << std::endl;            }
    00646   else                   { log << m_statPrintLevel << stars << endmsg; }
    00647 }
    00648
    00649 // ============================================================================
    00650 // The END
    00651 // ============================================================================