00001
00002
00003
00004
00005 #ifdef _WIN32
00006 #pragma warning( disable : 4786 )
00007 #endif
00008
00009
00010
00011 #include <iostream>
00012 #include <iomanip>
00013 #include <string>
00014 #include <algorithm>
00015 #include <functional>
00016 #include <fstream>
00017 #include <iomanip>
00018
00019
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
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
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
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
00099 , m_header ( " Counter | # | sum | mean/eff^* | rms/err^* | min | max |")
00100
00101 , m_format1 ( " %|-15.15s|%|17t||%|10d| |%|11.7g| |%|#11.5g| |%|#11.5g| |%|#12.5g| |%|#12.5g| |" )
00102
00103 , m_format2 ( "*%|-15.15s|%|17t||%|10d| |%|11.5g| |(%|#9.7g| +- %|-#9.7g|)%%| ------- | ------- |" )
00104
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
00145
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
00169
00170 ChronoStatSvc::~ChronoStatSvc()
00171 {
00172
00173 m_chronoEntities.clear();
00174
00175 m_statEntities.clear();
00176 }
00177
00178
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
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
00227
00228 StatusCode ChronoStatSvc::finalize()
00229 {
00230 std::string local = name()+".finalize()";
00232 MsgStream main_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 {
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
00271 if( m_chronoOrderFlag )
00272 { std::sort( tmpCont.begin() ,
00273 tmpCont.end() ,
00274 ComparePairOfChronoEntityAndChronoTag() ); }
00275
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(msgSvc(), *tag)
00291 << 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(msgSvc(), *tag)
00319 << 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(msgSvc(), *tag)
00347 << 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 main_log << MSG::INFO << " Service finalized successfully " << endmsg;
00370
00371 return Service::finalize();
00372 }
00373
00374
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
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
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
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
00425
00426 IChronoStatSvc::ChronoStatus
00427 ChronoStatSvc::chronoStatus
00428 ( const IChronoStatSvc::ChronoTag& chronoTag )
00429 { return m_chronoEntities[ chronoTag ].status(); }
00430
00431
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
00441 if (theIter==m_statEntities.end()){
00442
00443 StatEntity& theSe = m_statEntities[ statTag ];
00444 theStat=& theSe;
00445 theStat->setnEntriesBeforeReset(m_numberOfSkippedEventsForMemStat);
00446 }
00447 else
00448 {
00449
00450 theStat=&((*theIter).second);
00451 }
00452
00453 theStat->addFlag ( statFlag ) ;
00454 }
00455
00456
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
00466
00467
00468
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
00480
00481
00482
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
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
00508 out << std::scientific << std::setprecision(8) ;
00509 }
00510
00511
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
00522 std::sort( chronos.begin() ,
00523 chronos.end() ,
00524 ComparePairOfChronoEntityAndChronoTag() );
00525
00526
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
00538 out << "\n[" << *tag << "]\n";
00539
00540
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
00549 out << "\n";
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
00558 out << "\n";
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
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
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
00606 if ( m_statOrderFlag )
00607 { std::sort( tmpCont.begin() ,
00608 tmpCont.end() ,
00609 ComparePairOfStatEntityAndStatTag() ); }
00610
00611
00612 {
00613
00614 if ( m_statCoutFlag ) { std::cout << m_header << std::endl ; }
00615 else { log << m_statPrintLevel << m_header << endmsg ; }
00616 }
00617
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
00651