CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_4_5_patch3/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: 2011/06/08 22:32:43 $
00006  * $Revision: 1.16 $
00007  * $Author: rovere $
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 #include "FWCore/MessageLogger/interface/JobReport.h"
00015 
00016 using namespace std;
00017 using namespace edm;
00018 
00019 template <class T>
00020 static unsigned int getEmptyMetric(T * array, int lenx, int leny, int lenz)
00021 {
00022   // len{x,y,z} MUST include under/overflow bins.
00023   unsigned int len = lenx+leny+lenz;
00024   unsigned int result=0;
00025   // start from 1 to exclude underflow bin. The comparison is accurate
00026   // since it takes properly into account under/overflow bins, for all
00027   // kind of histograms.
00028   for (unsigned int i=1; i<len; ++i)
00029   {
00030     // get rid of under/overflow bins for x,y,z axis, to have a correct statistics.
00031     if (i%(lenx-1)==0)
00032       continue;
00033     if (i%lenx==0)
00034       continue;
00035     if (i%(lenx+leny-1)==0)
00036       continue;
00037     if (i%(lenx+leny)==0)
00038       continue;
00039     if (i%(lenx+leny+lenz-1)==0)
00040       continue;
00041   
00042     if (array[i] == 0)
00043       result += 1;
00044   }
00045   
00046   return result;
00047 }
00048 
00049 //==================================================================//
00050 //================= Constructor and Destructor =====================//
00051 //==================================================================//
00052 DQMStoreStats::DQMStoreStats( const edm::ParameterSet& ps )
00053   : subsystem_ (""),
00054     subfolder_ (""),
00055     nbinsglobal_ (0),
00056     nbinssubsys_ (0),
00057     nmeglobal_ (0),
00058     nmesubsys_ (0),
00059     maxbinsglobal_ (0),
00060     maxbinssubsys_ (0),
00061     maxbinsmeglobal_ (""),
00062     maxbinsmesubsys_ (""),
00063     statsdepth_ (1),
00064     pathnamematch_ ("*"),
00065     verbose_ (0)
00066 {
00067   parameters_ = ps;
00068   pathnamematch_ = ps.getUntrackedParameter<std::string>( "pathNameMatch", pathnamematch_ );
00069   statsdepth_ = ps.getUntrackedParameter<int>( "statsDepth", statsdepth_ );
00070   verbose_ = ps.getUntrackedParameter<int>( "verbose", verbose_ );
00071   dumpMemHistory_ = ps.getUntrackedParameter<bool>( "dumpMemoryHistory", false );
00072   runonendrun_    = ps.getUntrackedParameter<bool>( "runOnEndRun", true );
00073   runonendjob_    = ps.getUntrackedParameter<bool>( "runOnEndJob", false );
00074   runonendlumi_   = ps.getUntrackedParameter<bool>( "runOnEndLumi", false );
00075   runineventloop_ = ps.getUntrackedParameter<bool>( "runInEventLoop", false );
00076   dumpToFWJR_     = ps.getUntrackedParameter<bool>( "dumpToFWJR", false );
00077 
00078   startingTime_ = time( 0 );
00079 }
00080 
00081 DQMStoreStats::~DQMStoreStats(){
00082 }
00083 
00084 void DQMStoreStats::calcIgProfDump(Folder &root)
00085 {
00086   std::ofstream stream("dqm-bin-stats.sql");
00087   stream << ""
00088 "    PRAGMA journal_mode=OFF;"
00089 "    PRAGMA count_changes=OFF;"
00090 "    DROP TABLE IF EXISTS files;"
00091 "    DROP TABLE IF EXISTS symbols;"
00092 "    DROP TABLE IF EXISTS mainrows;"
00093 "    DROP TABLE IF EXISTS children;"
00094 "    DROP TABLE IF EXISTS parents;"
00095 "    DROP TABLE IF EXISTS summary;"
00096 "    CREATE TABLE children ("
00097 "        self_id INTEGER CONSTRAINT self_exists REFERENCES mainrows(id),"
00098 "        parent_id INTEGER CONSTRAINT parent_exists REFERENCES mainrows(id),"
00099 "        from_parent_count INTEGER,"
00100 "        from_parent_calls INTEGER,"
00101 "        from_parent_paths INTEGER,"
00102 "        pct REAL"
00103 "    );"
00104 "    CREATE TABLE files ("
00105 "        id,"
00106 "        name TEXT"
00107 "    );"
00108 "    CREATE TABLE mainrows ("
00109 "        id INTEGER PRIMARY KEY,"
00110 "        symbol_id INTEGER CONSTRAINT symbol_id_exists REFERENCES symbols(id),"
00111 "        self_count INTEGER,"
00112 "        cumulative_count INTEGER,"
00113 "        kids INTEGER,"
00114 "        self_calls INTEGER,"
00115 "        total_calls INTEGER,"
00116 "        self_paths INTEGER,"
00117 "        total_paths INTEGER,"
00118 "        pct REAL"
00119 "    );"
00120 "    CREATE TABLE parents ("
00121 "        self_id INTEGER CONSTRAINT self_exists REFERENCES mainrows(id),"
00122 "        child_id INTEGER CONSTRAINT child_exists REFERENCES mainrows(id),"
00123 "        to_child_count INTEGER,"
00124 "        to_child_calls INTEGER,"
00125 "        to_child_paths INTEGER,"
00126 "        pct REAL"
00127 "    );"
00128 "    CREATE TABLE summary ("
00129 "        counter TEXT,"
00130 "        total_count INTEGER,"
00131 "        total_freq INTEGER,"
00132 "        tick_period REAL"
00133 "    );"
00134 "    CREATE TABLE symbols ("
00135 "        id,"
00136 "        name TEXT,"
00137 "        filename_id INTEGER CONSTRAINT file_id_exists REFERENCES files(id)"
00138 "    );"
00139 "    CREATE UNIQUE INDEX fileIndex ON files (id);"
00140 "    CREATE INDEX selfCountIndex ON mainrows(self_count);"
00141 "    CREATE UNIQUE INDEX symbolsIndex ON symbols (id);"
00142 "    CREATE INDEX totalCountIndex ON mainrows(cumulative_count);" << std::endl;
00143 
00144   std::string sql_statement("");
00145 
00146   root.files(sql_statement);
00147   root.symbols(sql_statement);
00148   root.mainrows_cumulative(sql_statement);
00149   root.summary(sql_statement);
00150   VIterator<Folder *> subsystems = root.CreateIterator() ;
00151   size_t ii=0;
00152   for(subsystems.First() ; !subsystems.IsDone() ; subsystems.Next(), ++ii)
00153   {
00154     subsystems.CurrentItem()->mainrows(sql_statement);
00155     subsystems.CurrentItem()->parents(sql_statement);
00156     subsystems.CurrentItem()->children(sql_statement);
00157   }
00158   stream << sql_statement << std::endl;
00159 }
00160 
00167 int DQMStoreStats::calcstats( int mode = DQMStoreStats::considerAllME ) {
00168 
00170   nbinsglobal_ = 0; 
00171   nbinssubsys_ = 0; 
00172   maxbinsglobal_ = 0; 
00173   maxbinssubsys_ = 0; 
00174   std::string path = "";
00175   std::string subsystemname = "";
00176   std::string subfoldername = "";
00177   size_t subsysStringEnd = 0, subfolderStringBegin = 0, subfolderStringEnd  = 0;
00178 
00179 
00180   std::vector<MonitorElement*> melist;
00181   melist = dbe_->getMatchingContents( pathnamematch_ );
00182 
00183   Folder dbeFolder("root");
00184   DQMStoreStatsTopLevel dqmStoreStatsTopLevel;
00185 
00186   // loop all ME
00187   typedef std::vector <MonitorElement*>::iterator meIt;
00188   for(meIt it = melist.begin(); it != melist.end(); ++it) {
00189 
00190     // consider only ME with getLumiFlag() == true ?
00191     if( mode == DQMStoreStats::considerOnlyLumiProductME && 
00192         !( (*it)->getLumiFlag() ) ) continue;
00193     
00194     // figure out subsystem/subfolder names
00195     std::string path = (*it)->getPathname();
00196 
00197     subfolderStringBegin = 0;
00198     Folder * curr = &dbeFolder;
00199     while(1)
00200     {
00201       subfolderStringEnd = path.find( '/', subfolderStringBegin );
00202       if( std::string::npos == subfolderStringEnd )
00203       {
00204         curr = curr->cd(path.substr( subfolderStringBegin, path.size() ));
00205         break;
00206       }
00207       curr = curr->cd(path.substr( subfolderStringBegin, subfolderStringEnd-subfolderStringBegin ));
00208       subfolderStringBegin = subfolderStringEnd+1;
00209     }
00210     
00211     // protection against ghost ME with empty paths
00212     if( 0 == path.size() ) continue;
00213 
00214     subsysStringEnd = path.find( '/', 0 );
00215     if( std::string::npos == subsysStringEnd ) subsysStringEnd = path.size(); // no subfolder
00216 
00217     // new subsystem?
00218     if( path.substr( 0, subsysStringEnd ) != subsystemname ) {
00219       DQMStoreStatsSubsystem aSubsystem;
00220       subsystemname = path.substr( 0, subsysStringEnd );
00221       aSubsystem.subsystemName_ = subsystemname;
00222       dqmStoreStatsTopLevel.push_back( aSubsystem );
00223     }
00224 
00225     // get subfolder name (if there is one..)
00226     if( path.size() == subsysStringEnd ) {
00227       // no subfolders in subsystem, make dummy
00228       DQMStoreStatsSubfolder aSubfolder;
00229       aSubfolder.subfolderName_ = subsystemname; // <-- for tagging this case
00230       dqmStoreStatsTopLevel.back().push_back( aSubfolder );
00231     }
00232 
00233     else {
00234 
00235       // there is a subfolder, get its name
00236       subfolderStringEnd = path.find( '/', subsysStringEnd + 1 );
00237       if( std::string::npos == subfolderStringEnd ) subfolderStringEnd = path.size();
00238 
00239       // new subfolder?
00240       if( path.substr( subsysStringEnd + 1, subfolderStringEnd - subsysStringEnd - 1 ) != subfoldername ) {
00241         subfoldername = path.substr( subsysStringEnd + 1, subfolderStringEnd - subsysStringEnd - 1 );
00242         DQMStoreStatsSubfolder aSubfolder;
00243         aSubfolder.subfolderName_ = subfoldername;
00244         dqmStoreStatsTopLevel.back().push_back( aSubfolder );
00245       }
00246 
00247     }
00248 
00249     // shortcut
00250     DQMStoreStatsSubfolder& currentSubfolder = dqmStoreStatsTopLevel.back().back();
00251 
00252     switch( (*it)->kind() ) {
00253       
00254       // one-dim ME
00255     case MonitorElement::DQM_KIND_TH1F:
00256       currentSubfolder.AddBinsF( (*it)->getNbinsX(), getEmptyMetric((*it)->getTH1F()->GetArray(), (*it)->getTH1F()->fN, 0, 0) );
00257       curr->update( (*it)->getNbinsX(), getEmptyMetric((*it)->getTH1F()->GetArray(), (*it)->getTH1F()->fN, 0, 0),   (*it)->getNbinsX()*sizeof( float ) );
00258       break;
00259     case MonitorElement::DQM_KIND_TH1S:
00260       currentSubfolder.AddBinsS( (*it)->getNbinsX(), getEmptyMetric((*it)->getTH1S()->GetArray(), (*it)->getTH1S()->fN, 0, 0) );
00261       curr->update( (*it)->getNbinsX(), getEmptyMetric((*it)->getTH1S()->GetArray(), (*it)->getTH1S()->fN, 0, 0),   (*it)->getNbinsX()*sizeof( short ) );
00262       break;
00263     case MonitorElement::DQM_KIND_TH1D:
00264       currentSubfolder.AddBinsD( (*it)->getNbinsX(), getEmptyMetric((*it)->getTH1D()->GetArray(), (*it)->getTH1D()->fN, 0, 0) );
00265       curr->update( (*it)->getNbinsX(), getEmptyMetric((*it)->getTH1D()->GetArray(), (*it)->getTH1D()->fN, 0, 0),   (*it)->getNbinsX()*sizeof( double ) );
00266       break;
00267     case MonitorElement::DQM_KIND_TPROFILE:
00268       currentSubfolder.AddBinsD( (*it)->getNbinsX(), getEmptyMetric((*it)->getTProfile()->GetArray(), (*it)->getTProfile()->fN, 0, 0) );
00269       curr->update( (*it)->getNbinsX(), getEmptyMetric((*it)->getTProfile()->GetArray(), (*it)->getTProfile()->fN, 0, 0),   (*it)->getNbinsX()*sizeof( double ) );
00270       break;
00271 
00272       // two-dim ME
00273     case MonitorElement::DQM_KIND_TH2F:
00274       currentSubfolder.AddBinsF( (*it)->getNbinsX() * (*it)->getNbinsY(), getEmptyMetric((*it)->getTH2F()->GetArray(), (*it)->getNbinsX()+2,  (*it)->getNbinsY()+2, 0) );
00275       curr->update( (*it)->getNbinsX() * (*it)->getNbinsY(), getEmptyMetric((*it)->getTH2F()->GetArray(), (*it)->getNbinsX()+2,  (*it)->getNbinsY()+2, 0),  (*it)->getNbinsX() * (*it)->getNbinsY()*sizeof(float) );
00276       break;
00277     case MonitorElement::DQM_KIND_TH2S:
00278       currentSubfolder.AddBinsS( (*it)->getNbinsX() * (*it)->getNbinsY(), getEmptyMetric((*it)->getTH2S()->GetArray(), (*it)->getNbinsX()+2,  (*it)->getNbinsY()+2, 0) );
00279       curr->update( (*it)->getNbinsX() * (*it)->getNbinsY(), getEmptyMetric((*it)->getTH2S()->GetArray(), (*it)->getNbinsX()+2,  (*it)->getNbinsY()+2, 0), (*it)->getNbinsX() * (*it)->getNbinsY()*sizeof(short) );
00280       break;
00281     case MonitorElement::DQM_KIND_TH2D:
00282       currentSubfolder.AddBinsD( (*it)->getNbinsX() * (*it)->getNbinsY(), getEmptyMetric((*it)->getTH2D()->GetArray(), (*it)->getNbinsX()+2,  (*it)->getNbinsY()+2, 0) );
00283       curr->update( (*it)->getNbinsX() * (*it)->getNbinsY(), getEmptyMetric((*it)->getTH2D()->GetArray(), (*it)->getNbinsX()+2,  (*it)->getNbinsY()+2, 0), (*it)->getNbinsX() * (*it)->getNbinsY()*sizeof(double) );
00284       break;
00285     case MonitorElement::DQM_KIND_TPROFILE2D:
00286       currentSubfolder.AddBinsD( (*it)->getNbinsX() * (*it)->getNbinsY(), getEmptyMetric((*it)->getTProfile2D()->GetArray(), (*it)->getNbinsX()+2,  (*it)->getNbinsY()+2, 0) );
00287       curr->update( (*it)->getNbinsX() * (*it)->getNbinsY(), getEmptyMetric((*it)->getTProfile2D()->GetArray(), (*it)->getNbinsX()+2,  (*it)->getNbinsY()+2, 0), (*it)->getNbinsX() * (*it)->getNbinsY()*sizeof(double) );
00288       break;
00289  
00290       // three-dim ME
00291     case MonitorElement::DQM_KIND_TH3F: 
00292       currentSubfolder.AddBinsF( (*it)->getNbinsX() * (*it)->getNbinsY() * (*it)->getNbinsZ(), getEmptyMetric( (*it)->getTH3F()->GetArray(), (*it)->getNbinsX()+2,  (*it)->getNbinsY()+2,  (*it)->getNbinsZ()+2 ) );
00293       curr->update( (*it)->getNbinsX() * (*it)->getNbinsY() * (*it)->getNbinsZ(),
00294                     getEmptyMetric( (*it)->getTH3F()->GetArray(), (*it)->getNbinsX()+2,  (*it)->getNbinsY()+2,  (*it)->getNbinsZ()+2 ),
00295                     (*it)->getNbinsX() * (*it)->getNbinsY() * (*it)->getNbinsZ()*sizeof(float));
00296       break;
00297 
00298     default: {}
00299       // here we have a DQM_KIND_INVALID, DQM_KIND_INT, DQM_KIND_REAL or DQM_KIND_STRING
00300       // which we don't care much about. Alternatively:
00301 
00302       //   std::cerr << "[DQMStoreStats::calcstats] ** WARNING: monitor element of kind: " 
00303       //               << (*it)->kind() << ", name: \"" << (*it)->getName() << "\"\n"
00304       //               << "  in path: \"" << path << "\" not considered." << std::endl;
00305     }
00306   } 
00307 
00308   if( mode == DQMStoreStats::considerAllME )
00309     calcIgProfDump(dbeFolder);
00310 
00311   // OUTPUT
00312 
00313   std::cout << endl;
00314   std::cout << "===========================================================================================" << std::endl;
00315   std::cout << "[DQMStoreStats::calcstats] -- Dumping stats results ";
00316   if( mode == DQMStoreStats::considerAllME ) std::cout << "FOR ALL ME" << std::endl;
00317   else if( mode == DQMStoreStats::considerOnlyLumiProductME ) std::cout << "FOR LUMI PRODUCTS ONLY" << std::endl;
00318   std::cout << "===========================================================================================" << std::endl;
00319   std::cout << endl;
00320 
00321   std::cout << "------------------------------------------------------------------------------------------" << std::endl;
00322   std::cout << "Configuration:" << std::endl;
00323   std::cout << "------------------------------------------------------------------------------------------" << std::endl;
00324   std::cout << " > running ";
00325   if (runonendrun_) std::cout << "on run end." << std::endl;
00326   if (runonendlumi_) std::cout << "on lumi end." << std::endl;
00327   if (runonendjob_) std::cout << "on job end." << std::endl;
00328   if (runineventloop_) std::cout << "in event loop." << std::endl;
00329   std::cout << " > pathNameMatch = \"" << pathnamematch_ << "\"" << std::endl;
00330   std::cout << std::endl;
00331 
00332   // dump folder structure
00333   std::cout << "------------------------------------------------------------------------------------------" << std::endl;
00334   std::cout << "Top level folder tree:" << std::endl;
00335   std::cout << "------------------------------------------------------------------------------------------" << std::endl;
00336   for( DQMStoreStatsTopLevel::const_iterator it0 = dqmStoreStatsTopLevel.begin(); it0 < dqmStoreStatsTopLevel.end(); ++it0 ) {
00337     std::cout << it0->subsystemName_ << " (subsystem)" << std::endl;
00338     
00339     for( DQMStoreStatsSubsystem::const_iterator it1 = it0->begin(); it1 < it0->end(); ++it1 ) {
00340       std::cout << "  |--> " << it1->subfolderName_ << " (subfolder)" << std::endl;
00341     }
00342     
00343   }
00344 
00345   // dump mem/bin table
00346 
00347   unsigned int overallNHistograms = 0, overallNBins = 0, overallNEmptyBins = 0, overallNBytes = 0;
00348 
00349   std::cout << std::endl;
00350   std::cout << "------------------------------------------------------------------------------------------" << std::endl;
00351   std::cout << "Detailed ressource usage information ";
00352   if( mode == DQMStoreStats::considerAllME ) std::cout << "FOR ALL ME" << std::endl;
00353   else if( mode == DQMStoreStats::considerOnlyLumiProductME ) std::cout << "FOR LUMI PRODUCTS ONLY" << std::endl;
00354   std::cout << "------------------------------------------------------------------------------------------" << std::endl;
00355   std::cout << "subsystem/folder                          histograms       bins        Empty bins     Empty/Total      bins per       MB         kB per" << std::endl;
00356   std::cout << "                                           (total)        (total)        (total)                      histogram     (total)    histogram  " << std::endl;
00357   std::cout << "------------------------------------------------------------------------------------------" << std::endl;
00358   for( DQMStoreStatsTopLevel::const_iterator it0 = dqmStoreStatsTopLevel.begin(); it0 < dqmStoreStatsTopLevel.end(); ++it0 ) {
00359     std::cout << it0->subsystemName_ << std::endl;
00360     
00361     unsigned int nHistograms = 0, nBins = 0, nEmptyBins = 0, nBytes = 0;
00362 
00363     for( DQMStoreStatsSubsystem::const_iterator it1 = it0->begin(); it1 < it0->end(); ++it1 ) {
00364 
00365       // fixed-size working copy
00366       std::string thisSubfolderName( it1->subfolderName_ );
00367       if( thisSubfolderName.size() > 30 ) {
00368         thisSubfolderName.resize( 30 );
00369         thisSubfolderName.replace( thisSubfolderName.size() - 3, 3, 3, '.' );
00370       }
00371 
00372       std::cout << " -> " << std::setw( 30 ) << std::left << thisSubfolderName;
00373       std::cout << std::setw( 14 ) << std::right << it1->totalHistos_;
00374       std::cout << std::setw( 14 ) << std::right << it1->totalBins_;
00375       std::cout << std::setw( 14 ) << std::right << it1->totalEmptyBins_;
00376       std::cout << std::setw( 14 ) << std::right << std::setprecision( 3 ) << (float)it1->totalEmptyBins_/(float)it1->totalBins_;
00377 
00378       // bins/histogram, need to catch nan if histos=0
00379       if( it1->totalHistos_ ) {
00380         std::cout << std::setw( 14 ) << std::right << std::setprecision( 3 ) << it1->totalBins_ / float( it1->totalHistos_ );
00381       } 
00382       else std::cout << std::setw( 14 ) << std::right << "-";
00383 
00384       std::cout << std::setw( 14 ) << std::right << std::setprecision( 3 ) << it1->totalMemory_ / 1024. / 1024.;
00385 
00386       // mem/histogram, need to catch nan if histos=0
00387       if( it1->totalHistos_ ) {
00388         std::cout << std::setw( 14 ) << std::right << std::setprecision( 3 ) << it1->totalMemory_ / 1024. / it1->totalHistos_;
00389       }
00390       else std::cout << std::setw( 14 ) << std::right << "-";
00391 
00392       std::cout << std::endl;
00393 
00394       // collect totals
00395       nHistograms += it1->totalHistos_; 
00396       nBins       += it1->totalBins_;   
00397       nEmptyBins  += it1->totalEmptyBins_;   
00398       nBytes      += it1->totalMemory_; 
00399 
00400     }
00401 
00402 
00403 
00404 
00405     overallNHistograms += nHistograms;
00406     overallNBins       += nBins;
00407     overallNEmptyBins  += nEmptyBins;
00408     overallNBytes      += nBytes;
00409 
00410     // display totals
00411     std::cout << "    " << std::setw( 30 ) << std::left << "SUBSYSTEM TOTAL";
00412     std::cout << std::setw( 14 ) << std::right << nHistograms;
00413     std::cout << std::setw( 14 ) << std::right << nBins;
00414     std::cout << std::setw( 14 ) << std::right << nEmptyBins;
00415     std::cout << std::setw( 14 ) << std::right << (float)nEmptyBins/(float)nBins;
00416     std::cout << std::setw( 14 ) << std::right << std::setprecision( 3 ) << nBins / float( nHistograms );
00417     std::cout << std::setw( 14 ) << std::right << std::setprecision( 3 ) << nBytes / 1024. / 1000.;
00418     std::cout << std::setw( 14 ) << std::right << std::setprecision( 3 ) << nBytes / 1024. / nHistograms;
00419     std::cout << std::endl;
00420       
00421     std::cout << ".........................................................................................." << std::endl;
00422 
00423   }
00424 
00425 
00426   // dump total
00427   std::cout << std::endl;
00428   std::cout << "------------------------------------------------------------------------------------------" << std::endl;
00429   std::cout << "Grand total ";
00430   if( mode == DQMStoreStats::considerAllME ) std::cout << "FOR ALL ME:" << std::endl;
00431   else if( mode == DQMStoreStats::considerOnlyLumiProductME ) std::cout << "FOR LUMI PRODUCTS ONLY:" << std::endl;
00432   std::cout << "------------------------------------------------------------------------------------------" << std::endl;
00433   std::cout << "Number of subsystems: " << dqmStoreStatsTopLevel.size() << std::endl;
00434   std::cout << "Total number of histograms: " << overallNHistograms << " with: " << overallNBins << " bins alltogether" << std::endl;
00435   std::cout << "Total memory occupied by histograms (excl. overhead): " << overallNBytes / 1024. / 1000. << " MB" << std::endl;
00436 
00437 
00438 
00439   std::cout << endl;
00440   std::cout << "===========================================================================================" << std::endl;
00441   std::cout << "[DQMStoreStats::calcstats] -- End of output ";
00442   if( mode == DQMStoreStats::considerAllME ) std::cout << "FOR ALL ME." << std::endl;
00443   else if( mode == DQMStoreStats::considerOnlyLumiProductME ) std::cout << "FOR LUMI PRODUCTS ONLY." << std::endl;
00444   std::cout << "===========================================================================================" << std::endl;
00445   std::cout << endl;
00446 
00447   // Put together a simplified version of the complete dump that is
00448   // sent to std::cout. Just dump the very basic information,
00449   // i.e. summary for each folder, both for run and LS products.
00450   if (dumpToFWJR_)
00451   {
00452     edm::Service<edm::JobReport> jr;
00453     // Do not even try if the FWJR service is not available.
00454     if (!jr.isAvailable())
00455       return 0;
00456     // Prepare appropriate map to store FWJR output.
00457     std::map<std::string, std::string> jrInfo;
00458     unsigned int overallNHistograms = 0, overallNBins = 0, overallNBytes = 0;
00459 
00460     jrInfo["Source"] = "DQMServices/Components";
00461     jrInfo["FileClass"] = "DQMStoreStats";
00462     if (runonendrun_)
00463       jrInfo["DumpType"] = "EndRun";
00464     if (runonendlumi_)
00465       jrInfo["DumpType"] = "EndLumi";
00466     if (runonendjob_)
00467       jrInfo["DumpType"] = "EndJob";
00468     if (runineventloop_)
00469       jrInfo["DumpType"] = "EventLoop";
00470     if( mode == DQMStoreStats::considerAllME )
00471       jrInfo["Type"] = "RunProduct";
00472     else if( mode == DQMStoreStats::considerOnlyLumiProductME )
00473       jrInfo["Type"] = "LumiProduct";
00474 
00475 
00476     jrInfo["pathNameMatch"] = pathnamematch_;
00477 
00478     for (DQMStoreStatsTopLevel::const_iterator it0 = dqmStoreStatsTopLevel.begin(); it0 < dqmStoreStatsTopLevel.end(); ++it0 )
00479     {
00480       unsigned int nHistograms = 0, nBins = 0, nEmptyBins = 0, nBytes = 0;
00481       for( DQMStoreStatsSubsystem::const_iterator it1 = it0->begin(); it1 < it0->end(); ++it1 ) {
00482         // collect totals
00483         nHistograms += it1->totalHistos_; 
00484         nBins       += it1->totalBins_;   
00485         nEmptyBins  += it1->totalEmptyBins_;   
00486         nBytes      += it1->totalMemory_; 
00487       }
00488       overallNHistograms += nHistograms;
00489       overallNBins       += nBins;
00490       overallNBytes      += nBytes;
00491       std::stringstream iss("");
00492       iss << nHistograms;
00493       jrInfo[it0->subsystemName_ + std::string("_h")] = iss.str();
00494       iss.str("");iss<<nBins;
00495       jrInfo[it0->subsystemName_ + std::string("_b")]  = iss.str();
00496       iss.str("");iss<<nEmptyBins;
00497       jrInfo[it0->subsystemName_ + std::string("_be")]  = iss.str();
00498       iss.str("");iss<< ((float)nEmptyBins/(float)nBins);
00499       jrInfo[it0->subsystemName_ + std::string("_fbe")]  = iss.str();
00500       iss.str("");iss<< ((float)nBins/(float)nHistograms);
00501       jrInfo[it0->subsystemName_ + std::string("_b_h")]    = iss.str();
00502       iss.str("");iss<<nBytes / 1024. / 1024.;
00503       jrInfo[it0->subsystemName_ + std::string("_MB")]    = iss.str();
00504       iss.str("");iss<<nBytes / 1024. / nHistograms;
00505       jrInfo[it0->subsystemName_ + std::string("_Kb_h")] = iss.str();
00506     }
00507     jr->reportAnalysisFile("DQMStatsReport", jrInfo);
00508   }
00509 
00510   return 0;
00511 
00512 }
00513 
00514 
00515 
00519 void DQMStoreStats::dumpMemoryProfile( void ) {
00520 
00521   std::cout << std::endl;
00522   std::cout << "------------------------------------------------------------------------------------------" << std::endl;
00523   std::cout << "Memory profile:" << std::endl;
00524   std::cout << "------------------------------------------------------------------------------------------" << std::endl;
00525 
00526   // determine virtual memory maximum
00527   std::pair<time_t, unsigned int> maxItem( 0, 0 );
00528   for( std::vector<std::pair<time_t, unsigned int> >::const_iterator it = memoryHistoryVector_.begin();
00529        it < memoryHistoryVector_.end(); ++it ) {
00530     if( it->second > maxItem.second ) {
00531       maxItem = *it;
00532     }
00533   }
00534 
00535   std::stringstream rootOutputFileName;
00536   rootOutputFileName << "dqmStoreStats_memProfile_" << getpid() << ".root";
00537 
00538   // dump memory history to root file
00539   if( dumpMemHistory_ && isOpenProcFileSuccessful_ ) {
00540 
00541     TFile outputFile( rootOutputFileName.str().c_str(), "RECREATE" );
00542 
00543     int aTime;
00544     float aMb;
00545 
00546     TTree memHistoryTree( "dqmstorestats_memhistory", "memory history" );
00547     memHistoryTree.Branch( "seconds", &aTime, "seconds/I" );
00548     memHistoryTree.Branch( "megabytes", &aMb, "megabytes/F" );
00549     for( std::vector<std::pair<time_t, unsigned int> >::const_iterator it = memoryHistoryVector_.begin();
00550          it < memoryHistoryVector_.end(); ++it ) {
00551       aTime = it->first - startingTime_;
00552       aMb = it->second / 1000.;
00553       memHistoryTree.Fill();
00554     }
00555 
00556     outputFile.Write();
00557     outputFile.Close();
00558 
00559   }
00560 
00561   std::cout << "Approx. maximum total virtual memory size of job: ";
00562   if( isOpenProcFileSuccessful_ && memoryHistoryVector_.size() ) {
00563     std::cout << maxItem.second / 1000.
00564               << " MB (reached " << maxItem.first - startingTime_ << " sec. after constructor called)," << std::endl;
00565     std::cout << " memory history written to: " << rootOutputFileName.str() << " (" << memoryHistoryVector_.size() << " samples)" << std::endl;
00566   } else {
00567     std::cout << "(could not be determined)" << std::endl;
00568   }
00569 
00570   std::cout << std::endl << std::endl;
00571   
00572 }
00573 
00574 
00575 
00579 void DQMStoreStats::print(){
00580   // subsystem info printout
00581   std::cout << " ---------- " << subsystem_ << " ---------- " << std::endl;
00582   std::cout <<  "  " << subfolder_ << ": " ;
00583   std::cout <<  nmesubsys_ << " histograms with " 
00584             <<  nbinssubsys_  << " bins. " ; 
00585   if (nmesubsys_ > 0) std::cout <<  nbinssubsys_/nmesubsys_ << " bins/histogram " ;
00586   std::cout << std::endl;
00587   std::cout <<  "  Largest histogram: " << maxbinsmesubsys_ << " with " <<
00588                                          maxbinssubsys_ << " bins." <<  std::endl;
00589 }
00590 
00591 
00592 
00593 
00597 std::pair<unsigned int, unsigned int> DQMStoreStats::readMemoryEntry( void ) const {
00598   
00599   // see if initial test reading was successful
00600   if( isOpenProcFileSuccessful_ ) {
00601 
00602     std::ifstream procFile( procFileName_.str().c_str(), ios::in );
00603 
00604     std::string readBuffer( "" );
00605     unsigned int memSize = 0;
00606 
00607     // scan procfile
00608     while( !procFile.eof() ) {
00609       procFile >> readBuffer;
00610       if( std::string( "VmSize:" ) == readBuffer ) {
00611         procFile >> memSize;
00612         break;
00613       }
00614     }
00615 
00616     procFile.close();
00617     return std::pair<time_t, unsigned int>( time( 0 ), memSize );
00618   }
00619 
00620   return std::pair<time_t, unsigned int>( 0, 0 );
00621 
00622 }
00623 
00624 
00625 
00626 //==================================================================//
00627 //========================= beginJob ===============================//
00628 //==================================================================//
00629 void DQMStoreStats::beginJob() {
00630 
00632   dbe_ = Service<DQMStore>().operator->();
00633 
00634   // access the proc/ folder for memory information
00635   procFileName_ << "/proc/" << getpid() << "/status";
00636 
00637   // open for a test
00638   std::ifstream procFile( procFileName_.str().c_str(), ios::in );
00639 
00640   if( procFile.good() ) {
00641     isOpenProcFileSuccessful_ = true;
00642   }
00643   else {
00644     std::cerr << " [DQMStoreStats::beginJob] ** WARNING: could not open file: " << procFileName_.str() << std::endl;
00645     std::cerr << "  Total memory profile will not be available." << std::endl;
00646     isOpenProcFileSuccessful_ = false;
00647   }
00648 
00649   procFile.close();
00650 
00651 }
00652 
00653 //==================================================================//
00654 //========================= beginRun ===============================//
00655 //==================================================================//
00656 void DQMStoreStats::beginRun(const edm::Run& r, const EventSetup& context) {
00657 }
00658 
00659 
00660 //==================================================================//
00661 //==================== beginLuminosityBlock ========================//
00662 //==================================================================//
00663 void DQMStoreStats::beginLuminosityBlock(const LuminosityBlock& lumiSeg,
00664                                             const EventSetup& context) {
00665 }
00666 
00667 
00668 //==================================================================//
00669 //==================== analyse (takes each event) ==================//
00670 //==================================================================//
00671 void DQMStoreStats::analyze(const Event& iEvent, const EventSetup& iSetup) {
00672 
00673   //now read virtual memory size from proc folder
00674   memoryHistoryVector_.push_back( readMemoryEntry() );
00675 
00676   if (runineventloop_) {
00677     calcstats( DQMStoreStats::considerAllME );
00678     calcstats( DQMStoreStats::considerOnlyLumiProductME );
00679     dumpMemoryProfile();
00680   }
00681 
00682 }
00683 
00684 
00685 //==================================================================//
00686 //========================= endLuminosityBlock =====================//
00687 //==================================================================//
00688 void DQMStoreStats::endLuminosityBlock(const LuminosityBlock& lumiSeg,
00689                                           const EventSetup& context) {
00690   if (runonendlumi_) { 
00691     calcstats( DQMStoreStats::considerAllME );
00692     calcstats( DQMStoreStats::considerOnlyLumiProductME );
00693     dumpMemoryProfile();
00694   }
00695 
00696 }
00697 
00698 //==================================================================//
00699 //============================= endRun =============================//
00700 //==================================================================//
00701 void DQMStoreStats::endRun(const Run& r, const EventSetup& context) {
00702 
00703   if (runonendrun_) {
00704     calcstats( DQMStoreStats::considerAllME );
00705     calcstats( DQMStoreStats::considerOnlyLumiProductME );
00706     dumpMemoryProfile();
00707   }
00708 
00709 }
00710 
00711 //==================================================================//
00712 //============================= endJob =============================//
00713 //==================================================================//
00714 void DQMStoreStats::endJob() {
00715 
00716   if (runonendjob_) {
00717     calcstats( DQMStoreStats::considerAllME );
00718     calcstats( DQMStoreStats::considerOnlyLumiProductME );
00719     dumpMemoryProfile();
00720   }
00721 
00722 }