CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/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: 2012/08/17 15:44:22 $
00006  * $Revision: 1.17 $
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()-subfolderStringBegin ));
00205         break;
00206       }
00207       curr = curr->cd(path.substr( subfolderStringBegin, subfolderStringEnd-subfolderStringBegin ));
00208       subfolderStringBegin = ++subfolderStringEnd < path.size() ? subfolderStringEnd : path.size();
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       subfoldername = "";
00224     }
00225 
00226     // get subfolder name (if there is one..)
00227     if( path.size() == subsysStringEnd ) {
00228       // no subfolders in subsystem, make dummy
00229       DQMStoreStatsSubfolder aSubfolder;
00230       aSubfolder.subfolderName_ = subsystemname; // <-- for tagging this case
00231       dqmStoreStatsTopLevel.back().push_back( aSubfolder );
00232     }
00233 
00234     else {
00235 
00236       // there is a subfolder, get its name
00237       subfolderStringEnd = path.find( '/', subsysStringEnd + 1 );
00238       if( std::string::npos == subfolderStringEnd ) subfolderStringEnd = path.size();
00239 
00240       // new subfolder?
00241       if( path.substr( subsysStringEnd + 1, subfolderStringEnd - subsysStringEnd - 1 ) != subfoldername ) {
00242         subfoldername = path.substr( subsysStringEnd + 1, subfolderStringEnd - subsysStringEnd - 1 );
00243         DQMStoreStatsSubfolder aSubfolder;
00244         aSubfolder.subfolderName_ = subfoldername;
00245         dqmStoreStatsTopLevel.back().push_back( aSubfolder );
00246       }
00247 
00248     }
00249 
00250     // shortcut
00251     DQMStoreStatsSubfolder& currentSubfolder = dqmStoreStatsTopLevel.back().back();
00252 
00253     switch( (*it)->kind() ) {
00254       
00255       // one-dim ME
00256     case MonitorElement::DQM_KIND_TH1F:
00257       currentSubfolder.AddBinsF( (*it)->getNbinsX(), getEmptyMetric((*it)->getTH1F()->GetArray(), (*it)->getTH1F()->fN, 0, 0) );
00258       curr->update( (*it)->getNbinsX(), getEmptyMetric((*it)->getTH1F()->GetArray(), (*it)->getTH1F()->fN, 0, 0),   (*it)->getNbinsX()*sizeof( float ) );
00259       break;
00260     case MonitorElement::DQM_KIND_TH1S:
00261       currentSubfolder.AddBinsS( (*it)->getNbinsX(), getEmptyMetric((*it)->getTH1S()->GetArray(), (*it)->getTH1S()->fN, 0, 0) );
00262       curr->update( (*it)->getNbinsX(), getEmptyMetric((*it)->getTH1S()->GetArray(), (*it)->getTH1S()->fN, 0, 0),   (*it)->getNbinsX()*sizeof( short ) );
00263       break;
00264     case MonitorElement::DQM_KIND_TH1D:
00265       currentSubfolder.AddBinsD( (*it)->getNbinsX(), getEmptyMetric((*it)->getTH1D()->GetArray(), (*it)->getTH1D()->fN, 0, 0) );
00266       curr->update( (*it)->getNbinsX(), getEmptyMetric((*it)->getTH1D()->GetArray(), (*it)->getTH1D()->fN, 0, 0),   (*it)->getNbinsX()*sizeof( double ) );
00267       break;
00268     case MonitorElement::DQM_KIND_TPROFILE:
00269       currentSubfolder.AddBinsD( (*it)->getNbinsX(), getEmptyMetric((*it)->getTProfile()->GetArray(), (*it)->getTProfile()->fN, 0, 0) );
00270       curr->update( (*it)->getNbinsX(), getEmptyMetric((*it)->getTProfile()->GetArray(), (*it)->getTProfile()->fN, 0, 0),   (*it)->getNbinsX()*sizeof( double ) );
00271       break;
00272 
00273       // two-dim ME
00274     case MonitorElement::DQM_KIND_TH2F:
00275       currentSubfolder.AddBinsF( (*it)->getNbinsX() * (*it)->getNbinsY(), getEmptyMetric((*it)->getTH2F()->GetArray(), (*it)->getNbinsX()+2,  (*it)->getNbinsY()+2, 0) );
00276       curr->update( (*it)->getNbinsX() * (*it)->getNbinsY(), getEmptyMetric((*it)->getTH2F()->GetArray(), (*it)->getNbinsX()+2,  (*it)->getNbinsY()+2, 0),  (*it)->getNbinsX() * (*it)->getNbinsY()*sizeof(float) );
00277       break;
00278     case MonitorElement::DQM_KIND_TH2S:
00279       currentSubfolder.AddBinsS( (*it)->getNbinsX() * (*it)->getNbinsY(), getEmptyMetric((*it)->getTH2S()->GetArray(), (*it)->getNbinsX()+2,  (*it)->getNbinsY()+2, 0) );
00280       curr->update( (*it)->getNbinsX() * (*it)->getNbinsY(), getEmptyMetric((*it)->getTH2S()->GetArray(), (*it)->getNbinsX()+2,  (*it)->getNbinsY()+2, 0), (*it)->getNbinsX() * (*it)->getNbinsY()*sizeof(short) );
00281       break;
00282     case MonitorElement::DQM_KIND_TH2D:
00283       currentSubfolder.AddBinsD( (*it)->getNbinsX() * (*it)->getNbinsY(), getEmptyMetric((*it)->getTH2D()->GetArray(), (*it)->getNbinsX()+2,  (*it)->getNbinsY()+2, 0) );
00284       curr->update( (*it)->getNbinsX() * (*it)->getNbinsY(), getEmptyMetric((*it)->getTH2D()->GetArray(), (*it)->getNbinsX()+2,  (*it)->getNbinsY()+2, 0), (*it)->getNbinsX() * (*it)->getNbinsY()*sizeof(double) );
00285       break;
00286     case MonitorElement::DQM_KIND_TPROFILE2D:
00287       currentSubfolder.AddBinsD( (*it)->getNbinsX() * (*it)->getNbinsY(), getEmptyMetric((*it)->getTProfile2D()->GetArray(), (*it)->getNbinsX()+2,  (*it)->getNbinsY()+2, 0) );
00288       curr->update( (*it)->getNbinsX() * (*it)->getNbinsY(), getEmptyMetric((*it)->getTProfile2D()->GetArray(), (*it)->getNbinsX()+2,  (*it)->getNbinsY()+2, 0), (*it)->getNbinsX() * (*it)->getNbinsY()*sizeof(double) );
00289       break;
00290  
00291       // three-dim ME
00292     case MonitorElement::DQM_KIND_TH3F: 
00293       currentSubfolder.AddBinsF( (*it)->getNbinsX() * (*it)->getNbinsY() * (*it)->getNbinsZ(), getEmptyMetric( (*it)->getTH3F()->GetArray(), (*it)->getNbinsX()+2,  (*it)->getNbinsY()+2,  (*it)->getNbinsZ()+2 ) );
00294       curr->update( (*it)->getNbinsX() * (*it)->getNbinsY() * (*it)->getNbinsZ(),
00295                     getEmptyMetric( (*it)->getTH3F()->GetArray(), (*it)->getNbinsX()+2,  (*it)->getNbinsY()+2,  (*it)->getNbinsZ()+2 ),
00296                     (*it)->getNbinsX() * (*it)->getNbinsY() * (*it)->getNbinsZ()*sizeof(float));
00297       break;
00298 
00299     default: {}
00300       // here we have a DQM_KIND_INVALID, DQM_KIND_INT, DQM_KIND_REAL or DQM_KIND_STRING
00301       // which we don't care much about. Alternatively:
00302 
00303       //   std::cerr << "[DQMStoreStats::calcstats] ** WARNING: monitor element of kind: " 
00304       //               << (*it)->kind() << ", name: \"" << (*it)->getName() << "\"\n"
00305       //               << "  in path: \"" << path << "\" not considered." << std::endl;
00306     }
00307   } 
00308 
00309   if( mode == DQMStoreStats::considerAllME )
00310     calcIgProfDump(dbeFolder);
00311 
00312   // OUTPUT
00313 
00314   std::cout << endl;
00315   std::cout << "===========================================================================================" << std::endl;
00316   std::cout << "[DQMStoreStats::calcstats] -- Dumping stats results ";
00317   if( mode == DQMStoreStats::considerAllME ) std::cout << "FOR ALL ME" << std::endl;
00318   else if( mode == DQMStoreStats::considerOnlyLumiProductME ) std::cout << "FOR LUMI PRODUCTS ONLY" << std::endl;
00319   std::cout << "===========================================================================================" << std::endl;
00320   std::cout << endl;
00321 
00322   std::cout << "------------------------------------------------------------------------------------------" << std::endl;
00323   std::cout << "Configuration:" << std::endl;
00324   std::cout << "------------------------------------------------------------------------------------------" << std::endl;
00325   std::cout << " > running ";
00326   if (runonendrun_) std::cout << "on run end." << std::endl;
00327   if (runonendlumi_) std::cout << "on lumi end." << std::endl;
00328   if (runonendjob_) std::cout << "on job end." << std::endl;
00329   if (runineventloop_) std::cout << "in event loop." << std::endl;
00330   std::cout << " > pathNameMatch = \"" << pathnamematch_ << "\"" << std::endl;
00331   std::cout << std::endl;
00332 
00333   // dump folder structure
00334   std::cout << "------------------------------------------------------------------------------------------" << std::endl;
00335   std::cout << "Top level folder tree:" << std::endl;
00336   std::cout << "------------------------------------------------------------------------------------------" << std::endl;
00337   for( DQMStoreStatsTopLevel::const_iterator it0 = dqmStoreStatsTopLevel.begin(); it0 < dqmStoreStatsTopLevel.end(); ++it0 ) {
00338     std::cout << it0->subsystemName_ << " (subsystem)" << std::endl;
00339     
00340     for( DQMStoreStatsSubsystem::const_iterator it1 = it0->begin(); it1 < it0->end(); ++it1 ) {
00341       std::cout << "  |--> " << it1->subfolderName_ << " (subfolder)" << std::endl;
00342     }
00343     
00344   }
00345 
00346   // dump mem/bin table
00347 
00348   unsigned int overallNHistograms = 0, overallNBins = 0, overallNEmptyBins = 0, overallNBytes = 0;
00349 
00350   std::cout << std::endl;
00351   std::cout << "------------------------------------------------------------------------------------------" << std::endl;
00352   std::cout << "Detailed ressource usage information ";
00353   if( mode == DQMStoreStats::considerAllME ) std::cout << "FOR ALL ME" << std::endl;
00354   else if( mode == DQMStoreStats::considerOnlyLumiProductME ) std::cout << "FOR LUMI PRODUCTS ONLY" << std::endl;
00355   std::cout << "------------------------------------------------------------------------------------------" << std::endl;
00356   std::cout << "subsystem/folder                          histograms       bins        Empty bins     Empty/Total      bins per       MB         kB per" << std::endl;
00357   std::cout << "                                           (total)        (total)        (total)                      histogram     (total)    histogram  " << std::endl;
00358   std::cout << "------------------------------------------------------------------------------------------" << std::endl;
00359   for( DQMStoreStatsTopLevel::const_iterator it0 = dqmStoreStatsTopLevel.begin(); it0 < dqmStoreStatsTopLevel.end(); ++it0 ) {
00360     std::cout << it0->subsystemName_ << std::endl;
00361     
00362     unsigned int nHistograms = 0, nBins = 0, nEmptyBins = 0, nBytes = 0;
00363 
00364     for( DQMStoreStatsSubsystem::const_iterator it1 = it0->begin(); it1 < it0->end(); ++it1 ) {
00365 
00366       // fixed-size working copy
00367       std::string thisSubfolderName( it1->subfolderName_ );
00368       if( thisSubfolderName.size() > 30 ) {
00369         thisSubfolderName.resize( 30 );
00370         thisSubfolderName.replace( thisSubfolderName.size() - 3, 3, 3, '.' );
00371       }
00372 
00373       std::cout << " -> " << std::setw( 30 ) << std::left << thisSubfolderName;
00374       std::cout << std::setw( 14 ) << std::right << it1->totalHistos_;
00375       std::cout << std::setw( 14 ) << std::right << it1->totalBins_;
00376       std::cout << std::setw( 14 ) << std::right << it1->totalEmptyBins_;
00377       std::cout << std::setw( 14 ) << std::right << std::setprecision( 3 ) << (float)it1->totalEmptyBins_/(float)it1->totalBins_;
00378 
00379       // bins/histogram, need to catch nan if histos=0
00380       if( it1->totalHistos_ ) {
00381         std::cout << std::setw( 14 ) << std::right << std::setprecision( 3 ) << it1->totalBins_ / float( it1->totalHistos_ );
00382       } 
00383       else std::cout << std::setw( 14 ) << std::right << "-";
00384 
00385       std::cout << std::setw( 14 ) << std::right << std::setprecision( 3 ) << it1->totalMemory_ / 1024. / 1024.;
00386 
00387       // mem/histogram, need to catch nan if histos=0
00388       if( it1->totalHistos_ ) {
00389         std::cout << std::setw( 14 ) << std::right << std::setprecision( 3 ) << it1->totalMemory_ / 1024. / it1->totalHistos_;
00390       }
00391       else std::cout << std::setw( 14 ) << std::right << "-";
00392 
00393       std::cout << std::endl;
00394 
00395       // collect totals
00396       nHistograms += it1->totalHistos_; 
00397       nBins       += it1->totalBins_;   
00398       nEmptyBins  += it1->totalEmptyBins_;   
00399       nBytes      += it1->totalMemory_; 
00400 
00401     }
00402 
00403 
00404 
00405 
00406     overallNHistograms += nHistograms;
00407     overallNBins       += nBins;
00408     overallNEmptyBins  += nEmptyBins;
00409     overallNBytes      += nBytes;
00410 
00411     // display totals
00412     std::cout << "    " << std::setw( 30 ) << std::left << "SUBSYSTEM TOTAL";
00413     std::cout << std::setw( 14 ) << std::right << nHistograms;
00414     std::cout << std::setw( 14 ) << std::right << nBins;
00415     std::cout << std::setw( 14 ) << std::right << nEmptyBins;
00416     std::cout << std::setw( 14 ) << std::right << (float)nEmptyBins/(float)nBins;
00417     std::cout << std::setw( 14 ) << std::right << std::setprecision( 3 ) << nBins / float( nHistograms );
00418     std::cout << std::setw( 14 ) << std::right << std::setprecision( 3 ) << nBytes / 1024. / 1000.;
00419     std::cout << std::setw( 14 ) << std::right << std::setprecision( 3 ) << nBytes / 1024. / nHistograms;
00420     std::cout << std::endl;
00421       
00422     std::cout << ".........................................................................................." << std::endl;
00423 
00424   }
00425 
00426 
00427   // dump total
00428   std::cout << std::endl;
00429   std::cout << "------------------------------------------------------------------------------------------" << std::endl;
00430   std::cout << "Grand total ";
00431   if( mode == DQMStoreStats::considerAllME ) std::cout << "FOR ALL ME:" << std::endl;
00432   else if( mode == DQMStoreStats::considerOnlyLumiProductME ) std::cout << "FOR LUMI PRODUCTS ONLY:" << std::endl;
00433   std::cout << "------------------------------------------------------------------------------------------" << std::endl;
00434   std::cout << "Number of subsystems: " << dqmStoreStatsTopLevel.size() << std::endl;
00435   std::cout << "Total number of histograms: " << overallNHistograms << " with: " << overallNBins << " bins alltogether" << std::endl;
00436   std::cout << "Total memory occupied by histograms (excl. overhead): " << overallNBytes / 1024. / 1000. << " MB" << std::endl;
00437 
00438 
00439 
00440   std::cout << endl;
00441   std::cout << "===========================================================================================" << std::endl;
00442   std::cout << "[DQMStoreStats::calcstats] -- End of output ";
00443   if( mode == DQMStoreStats::considerAllME ) std::cout << "FOR ALL ME." << std::endl;
00444   else if( mode == DQMStoreStats::considerOnlyLumiProductME ) std::cout << "FOR LUMI PRODUCTS ONLY." << std::endl;
00445   std::cout << "===========================================================================================" << std::endl;
00446   std::cout << endl;
00447 
00448   // Put together a simplified version of the complete dump that is
00449   // sent to std::cout. Just dump the very basic information,
00450   // i.e. summary for each folder, both for run and LS products.
00451   if (dumpToFWJR_)
00452   {
00453     edm::Service<edm::JobReport> jr;
00454     // Do not even try if the FWJR service is not available.
00455     if (!jr.isAvailable())
00456       return 0;
00457     // Prepare appropriate map to store FWJR output.
00458     std::map<std::string, std::string> jrInfo;
00459     unsigned int overallNHistograms = 0, overallNBins = 0, overallNBytes = 0;
00460 
00461     jrInfo["Source"] = "DQMServices/Components";
00462     jrInfo["FileClass"] = "DQMStoreStats";
00463     if (runonendrun_)
00464       jrInfo["DumpType"] = "EndRun";
00465     if (runonendlumi_)
00466       jrInfo["DumpType"] = "EndLumi";
00467     if (runonendjob_)
00468       jrInfo["DumpType"] = "EndJob";
00469     if (runineventloop_)
00470       jrInfo["DumpType"] = "EventLoop";
00471     if( mode == DQMStoreStats::considerAllME )
00472       jrInfo["Type"] = "RunProduct";
00473     else if( mode == DQMStoreStats::considerOnlyLumiProductME )
00474       jrInfo["Type"] = "LumiProduct";
00475 
00476 
00477     jrInfo["pathNameMatch"] = pathnamematch_;
00478 
00479     for (DQMStoreStatsTopLevel::const_iterator it0 = dqmStoreStatsTopLevel.begin(); it0 < dqmStoreStatsTopLevel.end(); ++it0 )
00480     {
00481       unsigned int nHistograms = 0, nBins = 0, nEmptyBins = 0, nBytes = 0;
00482       for( DQMStoreStatsSubsystem::const_iterator it1 = it0->begin(); it1 < it0->end(); ++it1 ) {
00483         // collect totals
00484         nHistograms += it1->totalHistos_; 
00485         nBins       += it1->totalBins_;   
00486         nEmptyBins  += it1->totalEmptyBins_;   
00487         nBytes      += it1->totalMemory_; 
00488       }
00489       overallNHistograms += nHistograms;
00490       overallNBins       += nBins;
00491       overallNBytes      += nBytes;
00492       std::stringstream iss("");
00493       iss << nHistograms;
00494       jrInfo[it0->subsystemName_ + std::string("_h")] = iss.str();
00495       iss.str("");iss<<nBins;
00496       jrInfo[it0->subsystemName_ + std::string("_b")]  = iss.str();
00497       iss.str("");iss<<nEmptyBins;
00498       jrInfo[it0->subsystemName_ + std::string("_be")]  = iss.str();
00499       iss.str("");iss<< ((float)nEmptyBins/(float)nBins);
00500       jrInfo[it0->subsystemName_ + std::string("_fbe")]  = iss.str();
00501       iss.str("");iss<< ((float)nBins/(float)nHistograms);
00502       jrInfo[it0->subsystemName_ + std::string("_b_h")]    = iss.str();
00503       iss.str("");iss<<nBytes / 1024. / 1024.;
00504       jrInfo[it0->subsystemName_ + std::string("_MB")]    = iss.str();
00505       iss.str("");iss<<nBytes / 1024. / nHistograms;
00506       jrInfo[it0->subsystemName_ + std::string("_Kb_h")] = iss.str();
00507     }
00508     jr->reportAnalysisFile("DQMStatsReport", jrInfo);
00509   }
00510 
00511   return 0;
00512 
00513 }
00514 
00515 
00516 
00520 void DQMStoreStats::dumpMemoryProfile( void ) {
00521 
00522   std::cout << std::endl;
00523   std::cout << "------------------------------------------------------------------------------------------" << std::endl;
00524   std::cout << "Memory profile:" << std::endl;
00525   std::cout << "------------------------------------------------------------------------------------------" << std::endl;
00526 
00527   // determine virtual memory maximum
00528   std::pair<time_t, unsigned int> maxItem( 0, 0 );
00529   for( std::vector<std::pair<time_t, unsigned int> >::const_iterator it = memoryHistoryVector_.begin();
00530        it < memoryHistoryVector_.end(); ++it ) {
00531     if( it->second > maxItem.second ) {
00532       maxItem = *it;
00533     }
00534   }
00535 
00536   std::stringstream rootOutputFileName;
00537   rootOutputFileName << "dqmStoreStats_memProfile_" << getpid() << ".root";
00538 
00539   // dump memory history to root file
00540   if( dumpMemHistory_ && isOpenProcFileSuccessful_ ) {
00541 
00542     TFile outputFile( rootOutputFileName.str().c_str(), "RECREATE" );
00543 
00544     int aTime;
00545     float aMb;
00546 
00547     TTree memHistoryTree( "dqmstorestats_memhistory", "memory history" );
00548     memHistoryTree.Branch( "seconds", &aTime, "seconds/I" );
00549     memHistoryTree.Branch( "megabytes", &aMb, "megabytes/F" );
00550     for( std::vector<std::pair<time_t, unsigned int> >::const_iterator it = memoryHistoryVector_.begin();
00551          it < memoryHistoryVector_.end(); ++it ) {
00552       aTime = it->first - startingTime_;
00553       aMb = it->second / 1000.;
00554       memHistoryTree.Fill();
00555     }
00556 
00557     outputFile.Write();
00558     outputFile.Close();
00559 
00560   }
00561 
00562   std::cout << "Approx. maximum total virtual memory size of job: ";
00563   if( isOpenProcFileSuccessful_ && memoryHistoryVector_.size() ) {
00564     std::cout << maxItem.second / 1000.
00565               << " MB (reached " << maxItem.first - startingTime_ << " sec. after constructor called)," << std::endl;
00566     std::cout << " memory history written to: " << rootOutputFileName.str() << " (" << memoryHistoryVector_.size() << " samples)" << std::endl;
00567   } else {
00568     std::cout << "(could not be determined)" << std::endl;
00569   }
00570 
00571   std::cout << std::endl << std::endl;
00572   
00573 }
00574 
00575 
00576 
00580 void DQMStoreStats::print(){
00581   // subsystem info printout
00582   std::cout << " ---------- " << subsystem_ << " ---------- " << std::endl;
00583   std::cout <<  "  " << subfolder_ << ": " ;
00584   std::cout <<  nmesubsys_ << " histograms with " 
00585             <<  nbinssubsys_  << " bins. " ; 
00586   if (nmesubsys_ > 0) std::cout <<  nbinssubsys_/nmesubsys_ << " bins/histogram " ;
00587   std::cout << std::endl;
00588   std::cout <<  "  Largest histogram: " << maxbinsmesubsys_ << " with " <<
00589                                          maxbinssubsys_ << " bins." <<  std::endl;
00590 }
00591 
00592 
00593 
00594 
00598 std::pair<unsigned int, unsigned int> DQMStoreStats::readMemoryEntry( void ) const {
00599   
00600   // see if initial test reading was successful
00601   if( isOpenProcFileSuccessful_ ) {
00602 
00603     std::ifstream procFile( procFileName_.str().c_str(), ios::in );
00604 
00605     std::string readBuffer( "" );
00606     unsigned int memSize = 0;
00607 
00608     // scan procfile
00609     while( !procFile.eof() ) {
00610       procFile >> readBuffer;
00611       if( std::string( "VmSize:" ) == readBuffer ) {
00612         procFile >> memSize;
00613         break;
00614       }
00615     }
00616 
00617     procFile.close();
00618     return std::pair<time_t, unsigned int>( time( 0 ), memSize );
00619   }
00620 
00621   return std::pair<time_t, unsigned int>( 0, 0 );
00622 
00623 }
00624 
00625 
00626 
00627 //==================================================================//
00628 //========================= beginJob ===============================//
00629 //==================================================================//
00630 void DQMStoreStats::beginJob() {
00631 
00633   dbe_ = Service<DQMStore>().operator->();
00634 
00635   // access the proc/ folder for memory information
00636   procFileName_ << "/proc/" << getpid() << "/status";
00637 
00638   // open for a test
00639   std::ifstream procFile( procFileName_.str().c_str(), ios::in );
00640 
00641   if( procFile.good() ) {
00642     isOpenProcFileSuccessful_ = true;
00643   }
00644   else {
00645     std::cerr << " [DQMStoreStats::beginJob] ** WARNING: could not open file: " << procFileName_.str() << std::endl;
00646     std::cerr << "  Total memory profile will not be available." << std::endl;
00647     isOpenProcFileSuccessful_ = false;
00648   }
00649 
00650   procFile.close();
00651 
00652 }
00653 
00654 //==================================================================//
00655 //========================= beginRun ===============================//
00656 //==================================================================//
00657 void DQMStoreStats::beginRun(const edm::Run& r, const EventSetup& context) {
00658 }
00659 
00660 
00661 //==================================================================//
00662 //==================== beginLuminosityBlock ========================//
00663 //==================================================================//
00664 void DQMStoreStats::beginLuminosityBlock(const LuminosityBlock& lumiSeg,
00665                                             const EventSetup& context) {
00666 }
00667 
00668 
00669 //==================================================================//
00670 //==================== analyse (takes each event) ==================//
00671 //==================================================================//
00672 void DQMStoreStats::analyze(const Event& iEvent, const EventSetup& iSetup) {
00673 
00674   //now read virtual memory size from proc folder
00675   memoryHistoryVector_.push_back( readMemoryEntry() );
00676 
00677   if (runineventloop_) {
00678     calcstats( DQMStoreStats::considerAllME );
00679     calcstats( DQMStoreStats::considerOnlyLumiProductME );
00680     dumpMemoryProfile();
00681   }
00682 
00683 }
00684 
00685 
00686 //==================================================================//
00687 //========================= endLuminosityBlock =====================//
00688 //==================================================================//
00689 void DQMStoreStats::endLuminosityBlock(const LuminosityBlock& lumiSeg,
00690                                           const EventSetup& context) {
00691   if (runonendlumi_) { 
00692     calcstats( DQMStoreStats::considerAllME );
00693     calcstats( DQMStoreStats::considerOnlyLumiProductME );
00694     dumpMemoryProfile();
00695   }
00696 
00697 }
00698 
00699 //==================================================================//
00700 //============================= endRun =============================//
00701 //==================================================================//
00702 void DQMStoreStats::endRun(const Run& r, const EventSetup& context) {
00703 
00704   if (runonendrun_) {
00705     calcstats( DQMStoreStats::considerAllME );
00706     calcstats( DQMStoreStats::considerOnlyLumiProductME );
00707     dumpMemoryProfile();
00708   }
00709 
00710 }
00711 
00712 //==================================================================//
00713 //============================= endJob =============================//
00714 //==================================================================//
00715 void DQMStoreStats::endJob() {
00716 
00717   if (runonendjob_) {
00718     calcstats( DQMStoreStats::considerAllME );
00719     calcstats( DQMStoreStats::considerOnlyLumiProductME );
00720     dumpMemoryProfile();
00721   }
00722 
00723 }