CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch9/src/DQMServices/Components/src/DQMStoreStats.cc

Go to the documentation of this file.
00001 /*
00002  * \file DQMStoreStats.cc
00003  * \author Andreas Meyer
00004  * Last Update:
00005  * $Date: 2010/01/18 14:52:31 $
00006  * $Revision: 1.10 $
00007  * $Author: olzem $
00008  *
00009  * Description: Print out statistics of histograms in DQMStore
00010 */
00011 
00012 #include "DQMServices/Components/src/DQMStoreStats.h"
00013 #include "FWCore/ServiceRegistry/interface/Service.h"
00014 
00015 using namespace std;
00016 using namespace edm;
00017 
00018 //==================================================================//
00019 //================= Constructor and Destructor =====================//
00020 //==================================================================//
00021 DQMStoreStats::DQMStoreStats( const edm::ParameterSet& ps )
00022   : subsystem_ (""),
00023     subfolder_ (""),
00024     nbinsglobal_ (0),
00025     nbinssubsys_ (0),
00026     nmeglobal_ (0),
00027     nmesubsys_ (0),
00028     maxbinsglobal_ (0),
00029     maxbinssubsys_ (0),
00030     maxbinsmeglobal_ (""),
00031     maxbinsmesubsys_ (""),
00032     statsdepth_ (1),
00033     pathnamematch_ ("*"),
00034     verbose_ (0)
00035 {
00036   parameters_ = ps;
00037   pathnamematch_ = ps.getUntrackedParameter<std::string>( "pathNameMatch", pathnamematch_ );
00038   statsdepth_ = ps.getUntrackedParameter<int>( "statsDepth", statsdepth_ );
00039   verbose_ = ps.getUntrackedParameter<int>( "verbose", verbose_ );
00040   dumpMemHistory_ = ps.getUntrackedParameter<bool>( "dumpMemoryHistory", false );
00041   runonendrun_    = ps.getUntrackedParameter<bool>( "runOnEndRun", true );
00042   runonendjob_    = ps.getUntrackedParameter<bool>( "runOnEndJob", false );
00043   runonendlumi_   = ps.getUntrackedParameter<bool>( "runOnEndLumi", false );
00044   runineventloop_ = ps.getUntrackedParameter<bool>( "runInEventLoop", false );
00045 
00046   startingTime_ = time( 0 );
00047 
00048 }
00049 
00050 DQMStoreStats::~DQMStoreStats(){
00051 }
00052 
00053 
00060 int DQMStoreStats::calcstats( int mode = DQMStoreStats::considerAllME ) {
00061 
00063   nbinsglobal_ = 0; 
00064   nbinssubsys_ = 0; 
00065   maxbinsglobal_ = 0; 
00066   maxbinssubsys_ = 0; 
00067   std::string path = "";
00068   std::string subsystemname = "";
00069   std::string subfoldername = "";
00070   size_t subsysStringEnd = 0, subfolderStringEnd  = 0;
00071 
00072 
00073   std::vector<MonitorElement*> melist;
00074   melist = dbe_->getMatchingContents( pathnamematch_ );
00075 
00076   DQMStoreStatsTopLevel dqmStoreStatsTopLevel;
00077 
00078   // loop all ME
00079   typedef std::vector <MonitorElement*>::iterator meIt;
00080   for(meIt it = melist.begin(); it != melist.end(); ++it) {
00081 
00082     // consider only ME with getLumiFlag() == true ?
00083     if( mode == DQMStoreStats::considerOnlyLumiProductME && 
00084         !( (*it)->getLumiFlag() ) ) continue;
00085     
00086     // figure out subsystem/subfolder names
00087     std::string path = (*it)->getPathname();
00088 
00089     // protection against ghost ME with empty paths
00090     if( 0 == path.size() ) continue;
00091 
00092     subsysStringEnd = path.find( '/', 0 );
00093     if( std::string::npos == subsysStringEnd ) subsysStringEnd = path.size(); // no subfolder
00094 
00095     // new subsystem?
00096     if( path.substr( 0, subsysStringEnd ) != subsystemname ) {
00097       DQMStoreStatsSubsystem aSubsystem;
00098       subsystemname = path.substr( 0, subsysStringEnd );
00099       aSubsystem.subsystemName_ = subsystemname;
00100       dqmStoreStatsTopLevel.push_back( aSubsystem );
00101     }
00102 
00103     // get subfolder name (if there is one..)
00104     if( path.size() == subsysStringEnd ) {
00105       // no subfolders in subsystem, make dummy
00106       DQMStoreStatsSubfolder aSubfolder;
00107       aSubfolder.subfolderName_ = subsystemname; // <-- for tagging this case
00108       dqmStoreStatsTopLevel.back().push_back( aSubfolder );
00109     }
00110 
00111     else {
00112 
00113       // there is a subfolder, get its name
00114       subfolderStringEnd = path.find( '/', subsysStringEnd + 1 );
00115       if( std::string::npos == subfolderStringEnd ) subfolderStringEnd = path.size();
00116 
00117       // new subfolder?
00118       if( path.substr( subsysStringEnd + 1, subfolderStringEnd - subsysStringEnd - 1 ) != subfoldername ) {
00119         subfoldername = path.substr( subsysStringEnd + 1, subfolderStringEnd - subsysStringEnd - 1 );
00120         DQMStoreStatsSubfolder aSubfolder;
00121         aSubfolder.subfolderName_ = subfoldername;
00122         dqmStoreStatsTopLevel.back().push_back( aSubfolder );
00123       }
00124 
00125     }
00126 
00127     // shortcut
00128     DQMStoreStatsSubfolder& currentSubfolder = dqmStoreStatsTopLevel.back().back();
00129 
00130     switch( (*it)->kind() ) {
00131       
00132       // one-dim ME
00133       case MonitorElement::DQM_KIND_TH1F: currentSubfolder.AddBinsF( (*it)->getNbinsX() ); break;
00134       case MonitorElement::DQM_KIND_TH1S: currentSubfolder.AddBinsS( (*it)->getNbinsX() ); break;
00135       case MonitorElement::DQM_KIND_TH1D: currentSubfolder.AddBinsD( (*it)->getNbinsX() ); break;
00136       case MonitorElement::DQM_KIND_TPROFILE: currentSubfolder.AddBinsD( (*it)->getNbinsX() ); break;
00137 
00138       // two-dim ME
00139       case MonitorElement::DQM_KIND_TH2F: currentSubfolder.AddBinsF( (*it)->getNbinsX() * (*it)->getNbinsY() ); break;
00140       case MonitorElement::DQM_KIND_TH2S: currentSubfolder.AddBinsS( (*it)->getNbinsX() * (*it)->getNbinsY() ); break;
00141       case MonitorElement::DQM_KIND_TH2D: currentSubfolder.AddBinsD( (*it)->getNbinsX() * (*it)->getNbinsY() ); break;
00142       case MonitorElement::DQM_KIND_TPROFILE2D: currentSubfolder.AddBinsD( (*it)->getNbinsX() * (*it)->getNbinsY() ); break;
00143  
00144       // three-dim ME
00145       case MonitorElement::DQM_KIND_TH3F: 
00146         currentSubfolder.AddBinsF( (*it)->getNbinsX() * (*it)->getNbinsY() * (*it)->getNbinsZ() ); break;
00147 
00148       default: {}
00149         // here we have a DQM_KIND_INVALID, DQM_KIND_INT, DQM_KIND_REAL or DQM_KIND_STRING
00150         // which we don't care much about. Alternatively:
00151 
00152         //   std::cerr << "[DQMStoreStats::calcstats] ** WARNING: monitor element of kind: " 
00153         //             << (*it)->kind() << ", name: \"" << (*it)->getName() << "\"\n"
00154         //             << "  in path: \"" << path << "\" not considered." << std::endl;
00155     }
00156       
00157   } 
00158 
00159 
00160 
00161   // OUTPUT
00162 
00163   std::cout << endl;
00164   std::cout << "===========================================================================================" << std::endl;
00165   std::cout << "[DQMStoreStats::calcstats] -- Dumping stats results ";
00166   if( mode == DQMStoreStats::considerAllME ) std::cout << "FOR ALL ME" << std::endl;
00167   else if( mode == DQMStoreStats::considerOnlyLumiProductME ) std::cout << "FOR LUMI PRODUCTS ONLY" << std::endl;
00168   std::cout << "===========================================================================================" << std::endl;
00169   std::cout << endl;
00170 
00171   std::cout << "------------------------------------------------------------------------------------------" << std::endl;
00172   std::cout << "Configuration:" << std::endl;
00173   std::cout << "------------------------------------------------------------------------------------------" << std::endl;
00174   std::cout << " > running ";
00175   if (runonendrun_) std::cout << "on run end." << std::endl;
00176   if (runonendlumi_) std::cout << "on lumi end." << std::endl;
00177   if (runonendjob_) std::cout << "on job end." << std::endl;
00178   if (runineventloop_) std::cout << "in event loop." << std::endl;
00179   std::cout << " > pathNameMatch = \"" << pathnamematch_ << "\"" << std::endl;
00180   std::cout << std::endl;
00181 
00182   // dump folder structure
00183   std::cout << "------------------------------------------------------------------------------------------" << std::endl;
00184   std::cout << "Top level folder tree:" << std::endl;
00185   std::cout << "------------------------------------------------------------------------------------------" << std::endl;
00186   for( DQMStoreStatsTopLevel::const_iterator it0 = dqmStoreStatsTopLevel.begin(); it0 < dqmStoreStatsTopLevel.end(); ++it0 ) {
00187     std::cout << it0->subsystemName_ << " (subsystem)" << std::endl;
00188     
00189     for( DQMStoreStatsSubsystem::const_iterator it1 = it0->begin(); it1 < it0->end(); ++it1 ) {
00190       std::cout << "  |--> " << it1->subfolderName_ << " (subfolder)" << std::endl;
00191     }
00192     
00193   }
00194 
00195   // dump mem/bin table
00196 
00197   unsigned int overallNHistograms = 0, overallNBins = 0, overallNBytes = 0;
00198 
00199   std::cout << std::endl;
00200   std::cout << "------------------------------------------------------------------------------------------" << std::endl;
00201   std::cout << "Detailed ressource usage information ";
00202   if( mode == DQMStoreStats::considerAllME ) std::cout << "FOR ALL ME" << std::endl;
00203   else if( mode == DQMStoreStats::considerOnlyLumiProductME ) std::cout << "FOR LUMI PRODUCTS ONLY" << std::endl;
00204   std::cout << "------------------------------------------------------------------------------------------" << std::endl;
00205   std::cout << "subsystem/folder                  histograms     bins      bins per      MB        kB per" << std::endl;
00206   std::cout << "                                   (total)     (total)    histogram    (total)   histogram  " << std::endl;
00207   std::cout << "------------------------------------------------------------------------------------------" << std::endl;
00208   for( DQMStoreStatsTopLevel::const_iterator it0 = dqmStoreStatsTopLevel.begin(); it0 < dqmStoreStatsTopLevel.end(); ++it0 ) {
00209     std::cout << it0->subsystemName_ << std::endl;
00210     
00211     unsigned int nHistograms = 0, nBins = 0, nBytes = 0;
00212 
00213     for( DQMStoreStatsSubsystem::const_iterator it1 = it0->begin(); it1 < it0->end(); ++it1 ) {
00214 
00215       // fixed-size working copy
00216       std::string thisSubfolderName( it1->subfolderName_ );
00217       if( thisSubfolderName.size() > 30 ) {
00218         thisSubfolderName.resize( 30 );
00219         thisSubfolderName.replace( thisSubfolderName.size() - 3, 3, 3, '.' );
00220       }
00221 
00222       std::cout << " -> " << std::setw( 30 ) << std::left << thisSubfolderName;
00223       std::cout << std::setw( 7 ) << std::right << it1->totalHistos_;
00224       std::cout << std::setw( 12 ) << std::right << it1->totalBins_;
00225 
00226       // bins/histogram, need to catch nan if histos=0
00227       if( it1->totalHistos_ ) {
00228         std::cout << std::setw( 12 ) << std::right << std::setprecision( 3 ) << it1->totalBins_ / float( it1->totalHistos_ );
00229       } 
00230       else std::cout << std::setw( 12 ) << std::right << "-";
00231 
00232       std::cout << std::setw( 12 ) << std::right << std::setprecision( 3 ) << it1->totalMemory_ / 1024. / 1000.;
00233 
00234       // mem/histogram, need to catch nan if histos=0
00235       if( it1->totalHistos_ ) {
00236         std::cout << std::setw( 12 ) << std::right << std::setprecision( 3 ) << it1->totalMemory_ / 1024. / it1->totalHistos_;
00237       }
00238       else std::cout << std::setw( 12 ) << std::right << "-";
00239 
00240       std::cout << std::endl;
00241 
00242       // collect totals
00243       nHistograms += it1->totalHistos_; 
00244       nBins       += it1->totalBins_;   
00245       nBytes      += it1->totalMemory_; 
00246 
00247     }
00248 
00249 
00250 
00251 
00252     overallNHistograms += nHistograms;
00253     overallNBins       += nBins;
00254     overallNBytes      += nBytes;
00255 
00256     // display totals
00257     std::cout << "    " << std::setw( 30 ) << std::left << "SUBSYSTEM TOTAL";
00258     std::cout << std::setw( 7 ) << std::right << nHistograms;
00259     std::cout << std::setw( 12 ) << std::right << nBins;
00260     std::cout << std::setw( 12 ) << std::right << std::setprecision( 3 ) << nBins / float( nHistograms );
00261     std::cout << std::setw( 12 ) << std::right << std::setprecision( 3 ) << nBytes / 1024. / 1000.;
00262     std::cout << std::setw( 12 ) << std::right << std::setprecision( 3 ) << nBytes / 1024. / nHistograms;
00263     std::cout << std::endl;
00264       
00265     std::cout << ".........................................................................................." << std::endl;
00266 
00267   }
00268 
00269 
00270   // dump total
00271   std::cout << std::endl;
00272   std::cout << "------------------------------------------------------------------------------------------" << std::endl;
00273   std::cout << "Grand total ";
00274   if( mode == DQMStoreStats::considerAllME ) std::cout << "FOR ALL ME:" << std::endl;
00275   else if( mode == DQMStoreStats::considerOnlyLumiProductME ) std::cout << "FOR LUMI PRODUCTS ONLY:" << std::endl;
00276   std::cout << "------------------------------------------------------------------------------------------" << std::endl;
00277   std::cout << "Number of subsystems: " << dqmStoreStatsTopLevel.size() << std::endl;
00278   std::cout << "Total number of histograms: " << overallNHistograms << " with: " << overallNBins << " bins alltogether" << std::endl;
00279   std::cout << "Total memory occupied by histograms (excl. overhead): " << overallNBytes / 1024. / 1000. << " MB" << std::endl;
00280 
00281 
00282 
00283   std::cout << endl;
00284   std::cout << "===========================================================================================" << std::endl;
00285   std::cout << "[DQMStoreStats::calcstats] -- End of output ";
00286   if( mode == DQMStoreStats::considerAllME ) std::cout << "FOR ALL ME." << std::endl;
00287   else if( mode == DQMStoreStats::considerOnlyLumiProductME ) std::cout << "FOR LUMI PRODUCTS ONLY." << std::endl;
00288   std::cout << "===========================================================================================" << std::endl;
00289   std::cout << endl;
00290 
00291   return 0;
00292 
00293 }
00294 
00295 
00296 
00300 void DQMStoreStats::dumpMemoryProfile( void ) {
00301 
00302   std::cout << std::endl;
00303   std::cout << "------------------------------------------------------------------------------------------" << std::endl;
00304   std::cout << "Memory profile:" << std::endl;
00305   std::cout << "------------------------------------------------------------------------------------------" << std::endl;
00306 
00307   // determine virtual memory maximum
00308   std::pair<time_t, unsigned int> maxItem( 0, 0 );
00309   for( std::vector<std::pair<time_t, unsigned int> >::const_iterator it = memoryHistoryVector_.begin();
00310        it < memoryHistoryVector_.end(); ++it ) {
00311     if( it->second > maxItem.second ) {
00312       maxItem = *it;
00313     }
00314   }
00315 
00316   std::stringstream rootOutputFileName;
00317   rootOutputFileName << "dqmStoreStats_memProfile_" << getpid() << ".root";
00318 
00319   // dump memory history to root file
00320   if( dumpMemHistory_ && isOpenProcFileSuccessful_ ) {
00321 
00322     TFile outputFile( rootOutputFileName.str().c_str(), "RECREATE" );
00323 
00324     int aTime;
00325     float aMb;
00326 
00327     TTree memHistoryTree( "dqmstorestats_memhistory", "memory history" );
00328     memHistoryTree.Branch( "seconds", &aTime, "seconds/I" );
00329     memHistoryTree.Branch( "megabytes", &aMb, "megabytes/F" );
00330     for( std::vector<std::pair<time_t, unsigned int> >::const_iterator it = memoryHistoryVector_.begin();
00331          it < memoryHistoryVector_.end(); ++it ) {
00332       aTime = it->first - startingTime_;
00333       aMb = it->second / 1000.;
00334       memHistoryTree.Fill();
00335     }
00336 
00337     outputFile.Write();
00338     outputFile.Close();
00339 
00340   }
00341 
00342   std::cout << "Approx. maximum total virtual memory size of job: ";
00343   if( isOpenProcFileSuccessful_ && memoryHistoryVector_.size() ) {
00344     std::cout << maxItem.second / 1000.
00345               << " MB (reached " << maxItem.first - startingTime_ << " sec. after constructor called)," << std::endl;
00346     std::cout << " memory history written to: " << rootOutputFileName.str() << " (" << memoryHistoryVector_.size() << " samples)" << std::endl;
00347   } else {
00348     std::cout << "(could not be determined)" << std::endl;
00349   }
00350 
00351   std::cout << std::endl << std::endl;
00352   
00353 }
00354 
00355 
00356 
00360 void DQMStoreStats::print(){
00361   // subsystem info printout
00362   std::cout << " ---------- " << subsystem_ << " ---------- " << std::endl;
00363   std::cout <<  "  " << subfolder_ << ": " ;
00364   std::cout <<  nmesubsys_ << " histograms with " 
00365             <<  nbinssubsys_  << " bins. " ; 
00366   if (nmesubsys_ > 0) std::cout <<  nbinssubsys_/nmesubsys_ << " bins/histogram " ;
00367   std::cout << std::endl;
00368   std::cout <<  "  Largest histogram: " << maxbinsmesubsys_ << " with " <<
00369                                          maxbinssubsys_ << " bins." <<  std::endl;
00370 }
00371 
00372 
00373 
00374 
00378 std::pair<unsigned int, unsigned int> DQMStoreStats::readMemoryEntry( void ) const {
00379   
00380   // see if initial test reading was successful
00381   if( isOpenProcFileSuccessful_ ) {
00382 
00383     std::ifstream procFile( procFileName_.str().c_str(), ios::in );
00384 
00385     std::string readBuffer( "" );
00386     unsigned int memSize = 0;
00387 
00388     // scan procfile
00389     while( !procFile.eof() ) {
00390       procFile >> readBuffer;
00391       if( std::string( "VmSize:" ) == readBuffer ) {
00392         procFile >> memSize;
00393         break;
00394       }
00395     }
00396 
00397     procFile.close();
00398     return std::pair<time_t, unsigned int>( time( 0 ), memSize );
00399   }
00400 
00401   return std::pair<time_t, unsigned int>( 0, 0 );
00402 
00403 }
00404 
00405 
00406 
00407 //==================================================================//
00408 //========================= beginJob ===============================//
00409 //==================================================================//
00410 void DQMStoreStats::beginJob() {
00411 
00413   dbe_ = Service<DQMStore>().operator->();
00414 
00415   // access the proc/ folder for memory information
00416   procFileName_ << "/proc/" << getpid() << "/status";
00417 
00418   // open for a test
00419   std::ifstream procFile( procFileName_.str().c_str(), ios::in );
00420 
00421   if( procFile.good() ) {
00422     isOpenProcFileSuccessful_ = true;
00423   }
00424   else {
00425     std::cerr << " [DQMStoreStats::beginJob] ** WARNING: could not open file: " << procFileName_.str() << std::endl;
00426     std::cerr << "  Total memory profile will not be available." << std::endl;
00427     isOpenProcFileSuccessful_ = false;
00428   }
00429 
00430   procFile.close();
00431 
00432 }
00433 
00434 //==================================================================//
00435 //========================= beginRun ===============================//
00436 //==================================================================//
00437 void DQMStoreStats::beginRun(const edm::Run& r, const EventSetup& context) {
00438 }
00439 
00440 
00441 //==================================================================//
00442 //==================== beginLuminosityBlock ========================//
00443 //==================================================================//
00444 void DQMStoreStats::beginLuminosityBlock(const LuminosityBlock& lumiSeg,
00445                                             const EventSetup& context) {
00446 }
00447 
00448 
00449 //==================================================================//
00450 //==================== analyse (takes each event) ==================//
00451 //==================================================================//
00452 void DQMStoreStats::analyze(const Event& iEvent, const EventSetup& iSetup) {
00453 
00454   //now read virtual memory size from proc folder
00455   memoryHistoryVector_.push_back( readMemoryEntry() );
00456 
00457   if (runineventloop_) {
00458     calcstats( DQMStoreStats::considerAllME );
00459     calcstats( DQMStoreStats::considerOnlyLumiProductME );
00460     dumpMemoryProfile();
00461   }
00462 
00463 }
00464 
00465 
00466 //==================================================================//
00467 //========================= endLuminosityBlock =====================//
00468 //==================================================================//
00469 void DQMStoreStats::endLuminosityBlock(const LuminosityBlock& lumiSeg,
00470                                           const EventSetup& context) {
00471   if (runonendlumi_) { 
00472     calcstats( DQMStoreStats::considerAllME );
00473     calcstats( DQMStoreStats::considerOnlyLumiProductME );
00474     dumpMemoryProfile();
00475   }
00476 
00477 }
00478 
00479 //==================================================================//
00480 //============================= endRun =============================//
00481 //==================================================================//
00482 void DQMStoreStats::endRun(const Run& r, const EventSetup& context) {
00483 
00484   if (runonendrun_) {
00485     calcstats( DQMStoreStats::considerAllME );
00486     calcstats( DQMStoreStats::considerOnlyLumiProductME );
00487     dumpMemoryProfile();
00488   }
00489 
00490 }
00491 
00492 //==================================================================//
00493 //============================= endJob =============================//
00494 //==================================================================//
00495 void DQMStoreStats::endJob() {
00496 
00497   if (runonendjob_) {
00498     calcstats( DQMStoreStats::considerAllME );
00499     calcstats( DQMStoreStats::considerOnlyLumiProductME );
00500     dumpMemoryProfile();
00501   }
00502 
00503 }