Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-05-07 00:41:12

0001 /*
0002  * \file DQMStoreStats.cc
0003  * \author Andreas Meyer
0004  * Last Update:
0005  *
0006  * Description: Print out statistics of histograms in DQMStore
0007 */
0008 
0009 /** \class DQMStoreStats
0010  * *
0011  *  DQM Test Client
0012  *
0013  *  \author Andreas Meyer CERN
0014  *  \author Jan Olzem DESY
0015  *   
0016  */
0017 
0018 #include <string>
0019 #include <sstream>
0020 #include <utility>
0021 #include <vector>
0022 #include <iostream>
0023 #include <iomanip>
0024 #include <utility>
0025 #include <fstream>
0026 #include <sstream>
0027 
0028 #include "TFile.h"
0029 #include "TTree.h"
0030 
0031 #include "DQMServices/Core/interface/DQMStore.h"
0032 #include "FWCore/Framework/interface/one/EDAnalyzer.h"
0033 #include "FWCore/MessageLogger/interface/JobReport.h"
0034 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0035 #include "FWCore/ServiceRegistry/interface/Service.h"
0036 
0037 //
0038 // class declarations
0039 //
0040 
0041 using dqm::legacy::DQMStore;
0042 using dqm::legacy::MonitorElement;
0043 
0044 ///
0045 /// DQMStoreStats helper class for
0046 /// storing subsystem results
0047 ///
0048 class DQMStoreStatsSubfolder {
0049 public:
0050   DQMStoreStatsSubfolder() {
0051     totalHistos_ = 0;
0052     totalBins_ = 0;
0053     totalMemory_ = 0;
0054     totalEmptyBins_ = 0;
0055   }
0056   std::string subfolderName_;
0057   unsigned int totalHistos_;
0058   unsigned int totalBins_;
0059   unsigned int totalEmptyBins_;
0060   unsigned int totalMemory_;
0061   void AddBinsF(unsigned int nBins, unsigned int nEmptyBins) {
0062     ++totalHistos_;
0063     totalBins_ += nBins;
0064     totalEmptyBins_ += nEmptyBins;
0065     totalMemory_ += (nBins *= sizeof(float));
0066   }
0067   void AddBinsS(unsigned int nBins, unsigned int nEmptyBins) {
0068     ++totalHistos_;
0069     totalBins_ += nBins;
0070     totalEmptyBins_ += nEmptyBins;
0071     totalMemory_ += (nBins *= sizeof(short));
0072   }
0073   void AddBinsD(unsigned int nBins, unsigned int nEmptyBins) {
0074     ++totalHistos_;
0075     totalBins_ += nBins;
0076     totalEmptyBins_ += nEmptyBins;
0077     totalMemory_ += (nBins *= sizeof(double));
0078   }
0079   void AddBinsI(unsigned int nBins, unsigned int nEmptyBins) {
0080     ++totalHistos_;
0081     totalBins_ += nBins;
0082     totalEmptyBins_ += nEmptyBins;
0083     totalMemory_ += (nBins *= sizeof(int));
0084   }
0085 };
0086 
0087 ///
0088 /// DQMStoreStats helper class for
0089 /// storing subsystem results
0090 ///
0091 class DQMStoreStatsSubsystem : public std::vector<DQMStoreStatsSubfolder> {
0092 public:
0093   DQMStoreStatsSubsystem() = default;
0094   std::string subsystemName_;
0095 };
0096 
0097 ///
0098 /// DQMStoreStats helper class for
0099 /// storing subsystem results
0100 ///
0101 class DQMStoreStatsTopLevel : public std::vector<DQMStoreStatsSubsystem> {
0102 public:
0103   DQMStoreStatsTopLevel() = default;
0104 };
0105 
0106 template <class Item>
0107 class Iterator {
0108 public:
0109   virtual ~Iterator() = default;
0110   virtual void First() = 0;
0111   virtual void Next() = 0;
0112   virtual bool IsDone() const = 0;
0113   virtual Item CurrentItem() const = 0;
0114 
0115 protected:
0116   Iterator() = default;
0117 };
0118 
0119 template <class Item>
0120 class VIterator : public Iterator<Item> {
0121 public:
0122   VIterator(const std::vector<Item>* aVector) : vector_(aVector), index(0) {}
0123   ~VIterator() override = default;
0124   void First() override { index = 0; }
0125   void Next() override { ++index; }
0126   virtual int size() { return vector_->size(); }
0127   virtual int getIndex() { return (int)index; }
0128 
0129   bool IsDone() const override {
0130     if (index < (unsigned int)vector_->size())
0131       return false;
0132     return true;
0133   }
0134 
0135   Item CurrentItem() const override { return vector_->operator[](index); }
0136 
0137 private:
0138   const std::vector<Item>* vector_;
0139   unsigned int index;
0140 };
0141 
0142 static unsigned int getId() {
0143   static unsigned int id = 10;
0144   return ++id;
0145 }
0146 
0147 class Folder {
0148 public:
0149   Folder(std::string name)
0150       : totalHistos_(0),
0151         totalBins_(0),
0152         totalEmptyBins_(0),
0153         totalMemory_(0),
0154         id_(10),
0155         level_(0),
0156         folderName_(std::move(name)),
0157         father_(nullptr) {}
0158 
0159   ~Folder() {
0160     for (auto& subfolder : subfolders_)
0161       delete subfolder;
0162   }
0163 
0164   void setFather(Folder* e) { father_ = e; }
0165   Folder* getFather() { return father_; }
0166   const std::string& name() { return folderName_; }
0167 
0168   Folder* cd(const std::string& name) {
0169     for (auto& subfolder : subfolders_)
0170       if (subfolder->name() == name)
0171         return subfolder;
0172     auto* tmp = new Folder(name);
0173     this->add(tmp);
0174     return tmp;
0175   }
0176 
0177   void setId(unsigned int id) { id_ = id; }
0178   unsigned int id() { return id_; }
0179   void setLevel(unsigned int value) { level_ = value; }
0180   unsigned int level() { return level_; }
0181 
0182   void add(Folder* f) {
0183     f->setFather(this);
0184     subfolders_.push_back(f);
0185     f->setLevel(level_ + 1);
0186     f->setId(getId());
0187   }
0188 
0189   unsigned int getHistos() {
0190     unsigned int result = totalHistos_;
0191     for (auto& subfolder : subfolders_)
0192       result += subfolder->getHistos();
0193     return result;
0194   }
0195   unsigned int getBins() {
0196     unsigned int result = totalBins_;
0197     for (auto& subfolder : subfolders_)
0198       result += subfolder->getBins();
0199     return result;
0200   }
0201   unsigned int getEmptyBins() {
0202     unsigned int result = totalEmptyBins_;
0203     for (auto& subfolder : subfolders_)
0204       result += subfolder->getEmptyBins();
0205     return result;
0206   }
0207   unsigned int getMemory() {
0208     unsigned int result = totalMemory_;
0209     for (auto& subfolder : subfolders_)
0210       result += subfolder->getMemory();
0211     return result;
0212   }
0213   void update(unsigned int bins, unsigned int empty, unsigned int memory) {
0214     totalHistos_ += 1;
0215     totalBins_ += bins;
0216     totalEmptyBins_ += empty;
0217     totalMemory_ += memory;
0218   }
0219   void dump(std::string indent) {
0220     indent.append(" ");
0221     std::cout << indent << "I'm a " << name() << " whose father is " << getFather() << " with ID: " << id_
0222               << " Histo: " << getHistos() << " Bins: " << getBins() << " EmptyBins: " << getEmptyBins()
0223               << " Memory: " << getMemory() << " and my children are: " << std::endl;
0224     for (auto& subfolder : subfolders_)
0225       subfolder->dump(indent);
0226   }
0227   VIterator<Folder*> CreateIterator() { return VIterator<Folder*>(&subfolders_); }
0228 
0229   void mainrows(std::string& sql_statement) {
0230     std::stringstream s("");
0231     s << "INSERT INTO mainrows(id, symbol_id, self_count, cumulative_count, kids, self_calls, total_calls, self_paths, "
0232          "total_paths, pct)"
0233          " VALUES("
0234       << id_ << ", " << id_ << ", " << getMemory() << ", " << getMemory() << ", " << subfolders_.size() << ", "
0235       << getBins() - getEmptyBins() << ", " << getBins() << ", " << getHistos() << ", " << getHistos() << ", 0.0);\n";
0236     sql_statement.append(s.str());
0237     for (auto& subfolder : subfolders_)
0238       subfolder->mainrows(sql_statement);
0239   }
0240 
0241   void symbols(std::string& sql_statement) {
0242     unsigned int parentid = this->getFather() ? this->getFather()->id() : id_;
0243     std::stringstream s("");
0244     s << "INSERT INTO symbols(id, name, filename_id) VALUES (" << id_ << ",\"" << folderName_ << "\", " << parentid
0245       << ");\n";
0246     sql_statement.append(s.str());
0247     for (auto& subfolder : subfolders_)
0248       subfolder->symbols(sql_statement);
0249   }
0250 
0251   void parents(std::string& sql_statement) {
0252     unsigned int parentid = this->getFather() ? this->getFather()->id() : id_;
0253     std::stringstream s("");
0254     s << "INSERT INTO parents(self_id, child_id, to_child_count, to_child_calls, to_child_paths, pct) VALUES("
0255       << parentid << "," << id_ << "," << totalMemory_ << "," << totalBins_ << "," << totalHistos_ << ",0"
0256       << ");\n";
0257     sql_statement.append(s.str());
0258     for (auto& subfolder : subfolders_)
0259       subfolder->parents(sql_statement);
0260   }
0261 
0262   void children(std::string& sql_statement) {
0263     unsigned int parentid = this->getFather() ? this->getFather()->id() : id_;
0264     std::stringstream s("");
0265     s << "INSERT INTO children(self_id, parent_id, from_parent_count, from_parent_calls, from_parent_paths, pct) "
0266          "VALUES("
0267       << id_ << "," << parentid << "," << getMemory() << "," << getBins() - getEmptyBins() << "," << totalHistos_
0268       << ",0"
0269       << ");\n";
0270     sql_statement.append(s.str());
0271     for (auto& subfolder : subfolders_)
0272       subfolder->children(sql_statement);
0273   }
0274 
0275   void mainrows_cumulative(std::string& sql_statement) {
0276     std::stringstream s("");
0277     s << "INSERT INTO mainrows(id, symbol_id, self_count, cumulative_count, kids, self_calls, total_calls, self_paths, "
0278          "total_paths, pct)"
0279       << " VALUES(" << id_ << "," << id_ << "," << 0 << "," << getMemory() << ", 0," << getBins() - getEmptyBins()
0280       << "," << getBins() << ", 0, " << getHistos() << ", 0);\n";
0281     sql_statement.append(s.str());
0282   }
0283 
0284   void summary(std::string& sql_statement) {
0285     std::stringstream s("");
0286     s << "INSERT INTO summary(counter, total_count, total_freq, tick_period) VALUES (\"BINS_LIVE\"," << getMemory()
0287       << "," << getBins() << ", 1);\n";
0288     sql_statement.append(s.str());
0289   }
0290 
0291   void files(std::string& sql_statement) {
0292     std::stringstream s("");
0293     s << "INSERT INTO files(id, name) VALUES(" << id_ << ",\"" << folderName_ << "\");\n";
0294     sql_statement.append(s.str());
0295   }
0296 
0297 private:
0298   unsigned int totalHistos_;
0299   unsigned int totalBins_;
0300   unsigned int totalEmptyBins_;
0301   unsigned int totalMemory_;
0302   unsigned int id_;
0303   unsigned int level_;
0304   std::string folderName_;
0305   Folder* father_;
0306   std::vector<Folder*> subfolders_;
0307 };
0308 
0309 ///
0310 /// DQMStoreStats itself
0311 ///
0312 class DQMStoreStats : public edm::one::EDAnalyzer<edm::one::WatchRuns, edm::one::WatchLuminosityBlocks> {
0313 public:
0314   DQMStoreStats(const edm::ParameterSet&);
0315   ~DQMStoreStats() override = default;
0316 
0317   enum statsMode { considerAllME = 0, considerOnlyLumiProductME = 1 };
0318 
0319 protected:
0320   // BeginJob
0321   void beginJob() override;
0322 
0323   // BeginRun
0324   void beginRun(const edm::Run& r, const edm::EventSetup& c) override;
0325 
0326   // Fake Analyze
0327   void analyze(const edm::Event& e, const edm::EventSetup& c) override;
0328 
0329   // DQM Client Diagnostic
0330   void beginLuminosityBlock(const edm::LuminosityBlock& lumiSeg, const edm::EventSetup& c) override;
0331   void endLuminosityBlock(const edm::LuminosityBlock& lumiSeg, const edm::EventSetup& c) override;
0332 
0333   // EndRun
0334   void endRun(const edm::Run& r, const edm::EventSetup& c) override;
0335 
0336   // Endjob
0337   void endJob() override;
0338 
0339 private:
0340   int calcstats(int);
0341   void calcIgProfDump(Folder&);
0342   void dumpMemoryProfile();
0343   std::pair<unsigned int, unsigned int> readMemoryEntry() const;
0344   void print();
0345 
0346   DQMStore* dbe_;
0347   edm::ParameterSet parameters_;
0348 
0349   std::string subsystem_;
0350   std::string subfolder_;
0351   int nbinsglobal_;
0352   int nbinssubsys_;
0353   int nmeglobal_;
0354   int nmesubsys_;
0355   int maxbinsglobal_;
0356   int maxbinssubsys_;
0357   std::string maxbinsmeglobal_;
0358   std::string maxbinsmesubsys_;
0359 
0360   int statsdepth_;
0361   std::string pathnamematch_;
0362   int verbose_;
0363 
0364   std::vector<std::pair<time_t, unsigned int> > memoryHistoryVector_;
0365   time_t startingTime_;
0366   bool isOpenProcFileSuccessful_;
0367   std::stringstream procFileName_;
0368 
0369   bool runonendrun_;
0370   bool runonendjob_;
0371   bool runonendlumi_;
0372   bool runineventloop_;
0373   bool dumpMemHistory_;
0374   bool dumpToFWJR_;
0375 
0376   // ---------- member data ----------
0377 };
0378 
0379 using namespace std;
0380 using namespace edm;
0381 
0382 template <class T>
0383 static unsigned int getEmptyMetric(T* array, int lenx, int leny, int lenz) {
0384   // len{x,y,z} MUST include under/overflow bins.
0385   unsigned int len = lenx + leny + lenz;
0386   unsigned int result = 0;
0387   // start from 1 to exclude underflow bin. The comparison is accurate
0388   // since it takes properly into account under/overflow bins, for all
0389   // kind of histograms.
0390   for (unsigned int i = 1; i < len; ++i) {
0391     // get rid of under/overflow bins for x,y,z axis, to have a correct statistics.
0392     if (i % (lenx - 1) == 0)
0393       continue;
0394     if (i % lenx == 0)
0395       continue;
0396     if (i % (lenx + leny - 1) == 0)
0397       continue;
0398     if (i % (lenx + leny) == 0)
0399       continue;
0400     if (i % (lenx + leny + lenz - 1) == 0)
0401       continue;
0402 
0403     if (array[i] == 0)
0404       result += 1;
0405   }
0406 
0407   return result;
0408 }
0409 
0410 //==================================================================//
0411 //================= Constructor and Destructor =====================//
0412 //==================================================================//
0413 DQMStoreStats::DQMStoreStats(const edm::ParameterSet& ps)
0414     : subsystem_(""),
0415       subfolder_(""),
0416       nbinsglobal_(0),
0417       nbinssubsys_(0),
0418       nmeglobal_(0),
0419       nmesubsys_(0),
0420       maxbinsglobal_(0),
0421       maxbinssubsys_(0),
0422       maxbinsmeglobal_(""),
0423       maxbinsmesubsys_(""),
0424       statsdepth_(1),
0425       pathnamematch_(""),
0426       verbose_(0) {
0427   parameters_ = ps;
0428   pathnamematch_ = ps.getUntrackedParameter<std::string>("pathNameMatch", pathnamematch_);
0429   statsdepth_ = ps.getUntrackedParameter<int>("statsDepth", statsdepth_);
0430   verbose_ = ps.getUntrackedParameter<int>("verbose", verbose_);
0431   dumpMemHistory_ = ps.getUntrackedParameter<bool>("dumpMemoryHistory", false);
0432   runonendrun_ = ps.getUntrackedParameter<bool>("runOnEndRun", true);
0433   runonendjob_ = ps.getUntrackedParameter<bool>("runOnEndJob", false);
0434   runonendlumi_ = ps.getUntrackedParameter<bool>("runOnEndLumi", false);
0435   runineventloop_ = ps.getUntrackedParameter<bool>("runInEventLoop", false);
0436   dumpToFWJR_ = ps.getUntrackedParameter<bool>("dumpToFWJR", false);
0437 
0438   startingTime_ = time(nullptr);
0439 }
0440 
0441 void DQMStoreStats::calcIgProfDump(Folder& root) {
0442   std::ofstream stream("dqm-bin-stats.sql");
0443   stream << ""
0444             "    PRAGMA journal_mode=OFF;"
0445             "    PRAGMA count_changes=OFF;"
0446             "    DROP TABLE IF EXISTS files;"
0447             "    DROP TABLE IF EXISTS symbols;"
0448             "    DROP TABLE IF EXISTS mainrows;"
0449             "    DROP TABLE IF EXISTS children;"
0450             "    DROP TABLE IF EXISTS parents;"
0451             "    DROP TABLE IF EXISTS summary;"
0452             "    CREATE TABLE children ("
0453             "        self_id INTEGER CONSTRAINT self_exists REFERENCES mainrows(id),"
0454             "        parent_id INTEGER CONSTRAINT parent_exists REFERENCES mainrows(id),"
0455             "        from_parent_count INTEGER,"
0456             "        from_parent_calls INTEGER,"
0457             "        from_parent_paths INTEGER,"
0458             "        pct REAL"
0459             "    );"
0460             "    CREATE TABLE files ("
0461             "        id,"
0462             "        name TEXT"
0463             "    );"
0464             "    CREATE TABLE mainrows ("
0465             "        id INTEGER PRIMARY KEY,"
0466             "        symbol_id INTEGER CONSTRAINT symbol_id_exists REFERENCES symbols(id),"
0467             "        self_count INTEGER,"
0468             "        cumulative_count INTEGER,"
0469             "        kids INTEGER,"
0470             "        self_calls INTEGER,"
0471             "        total_calls INTEGER,"
0472             "        self_paths INTEGER,"
0473             "        total_paths INTEGER,"
0474             "        pct REAL"
0475             "    );"
0476             "    CREATE TABLE parents ("
0477             "        self_id INTEGER CONSTRAINT self_exists REFERENCES mainrows(id),"
0478             "        child_id INTEGER CONSTRAINT child_exists REFERENCES mainrows(id),"
0479             "        to_child_count INTEGER,"
0480             "        to_child_calls INTEGER,"
0481             "        to_child_paths INTEGER,"
0482             "        pct REAL"
0483             "    );"
0484             "    CREATE TABLE summary ("
0485             "        counter TEXT,"
0486             "        total_count INTEGER,"
0487             "        total_freq INTEGER,"
0488             "        tick_period REAL"
0489             "    );"
0490             "    CREATE TABLE symbols ("
0491             "        id,"
0492             "        name TEXT,"
0493             "        filename_id INTEGER CONSTRAINT file_id_exists REFERENCES files(id)"
0494             "    );"
0495             "    CREATE UNIQUE INDEX fileIndex ON files (id);"
0496             "    CREATE INDEX selfCountIndex ON mainrows(self_count);"
0497             "    CREATE UNIQUE INDEX symbolsIndex ON symbols (id);"
0498             "    CREATE INDEX totalCountIndex ON mainrows(cumulative_count);"
0499          << std::endl;
0500 
0501   std::string sql_statement("");
0502 
0503   root.files(sql_statement);
0504   root.symbols(sql_statement);
0505   root.mainrows_cumulative(sql_statement);
0506   root.summary(sql_statement);
0507   VIterator<Folder*> subsystems = root.CreateIterator();
0508   size_t ii = 0;
0509   for (subsystems.First(); !subsystems.IsDone(); subsystems.Next(), ++ii) {
0510     subsystems.CurrentItem()->mainrows(sql_statement);
0511     subsystems.CurrentItem()->parents(sql_statement);
0512     subsystems.CurrentItem()->children(sql_statement);
0513   }
0514   stream << sql_statement << std::endl;
0515 }
0516 
0517 ///
0518 /// do the stats here and produce output;
0519 ///
0520 /// mode is coded in DQMStoreStats::statMode enum
0521 /// (select subsets of ME, e.g. those with getLumiFlag() == true)
0522 ///
0523 int DQMStoreStats::calcstats(int mode = DQMStoreStats::considerAllME) {
0524   ////---- initialise Event and LS counters
0525   nbinsglobal_ = 0;
0526   nbinssubsys_ = 0;
0527   maxbinsglobal_ = 0;
0528   maxbinssubsys_ = 0;
0529   std::string path = "";
0530   std::string subsystemname = "";
0531   std::string subfoldername = "";
0532   size_t subsysStringEnd = 0, subfolderStringBegin = 0, subfolderStringEnd = 0;
0533 
0534   std::vector<MonitorElement*> melist;
0535   melist = dbe_->getAllContents(pathnamematch_);
0536 
0537   Folder dbeFolder("root");
0538   DQMStoreStatsTopLevel dqmStoreStatsTopLevel;
0539 
0540   // loop all ME
0541   for (auto& it : melist) {
0542     // consider only ME with getLumiFlag() == true ?
0543     if (mode == DQMStoreStats::considerOnlyLumiProductME && !(it->getLumiFlag()))
0544       continue;
0545 
0546     // figure out subsystem/subfolder names
0547     const std::string& path = it->getPathname();
0548 
0549     subfolderStringBegin = 0;
0550     Folder* curr = &dbeFolder;
0551     while (true) {
0552       subfolderStringEnd = path.find('/', subfolderStringBegin);
0553       if (std::string::npos == subfolderStringEnd) {
0554         curr = curr->cd(path.substr(subfolderStringBegin, path.size() - subfolderStringBegin));
0555         break;
0556       }
0557       curr = curr->cd(path.substr(subfolderStringBegin, subfolderStringEnd - subfolderStringBegin));
0558       subfolderStringBegin = ++subfolderStringEnd < path.size() ? subfolderStringEnd : path.size();
0559     }
0560 
0561     // protection against ghost ME with empty paths
0562     if (path.empty())
0563       continue;
0564 
0565     subsysStringEnd = path.find('/', 0);
0566     if (std::string::npos == subsysStringEnd)
0567       subsysStringEnd = path.size();  // no subfolder
0568 
0569     // new subsystem?
0570     if (path.substr(0, subsysStringEnd) != subsystemname) {
0571       DQMStoreStatsSubsystem aSubsystem;
0572       subsystemname = path.substr(0, subsysStringEnd);
0573       aSubsystem.subsystemName_ = subsystemname;
0574       dqmStoreStatsTopLevel.push_back(aSubsystem);
0575       subfoldername = "";
0576     }
0577 
0578     // get subfolder name (if there is one..)
0579     if (path.size() == subsysStringEnd) {
0580       // no subfolders in subsystem, make dummy
0581       DQMStoreStatsSubfolder aSubfolder;
0582       aSubfolder.subfolderName_ = subsystemname;  // <-- for tagging this case
0583       dqmStoreStatsTopLevel.back().push_back(aSubfolder);
0584     }
0585 
0586     else {
0587       // there is a subfolder, get its name
0588       subfolderStringEnd = path.find('/', subsysStringEnd + 1);
0589       if (std::string::npos == subfolderStringEnd)
0590         subfolderStringEnd = path.size();
0591 
0592       // new subfolder?
0593       if (path.substr(subsysStringEnd + 1, subfolderStringEnd - subsysStringEnd - 1) != subfoldername) {
0594         subfoldername = path.substr(subsysStringEnd + 1, subfolderStringEnd - subsysStringEnd - 1);
0595         DQMStoreStatsSubfolder aSubfolder;
0596         aSubfolder.subfolderName_ = subfoldername;
0597         dqmStoreStatsTopLevel.back().push_back(aSubfolder);
0598       }
0599     }
0600 
0601     // shortcut
0602     DQMStoreStatsSubfolder& currentSubfolder = dqmStoreStatsTopLevel.back().back();
0603 
0604     switch (it->kind()) {
0605         // one-dim ME
0606       case MonitorElement::Kind::TH1F:
0607         currentSubfolder.AddBinsF(it->getNbinsX(), getEmptyMetric(it->getTH1F()->GetArray(), it->getTH1F()->fN, 0, 0));
0608         curr->update(it->getNbinsX(),
0609                      getEmptyMetric(it->getTH1F()->GetArray(), it->getTH1F()->fN, 0, 0),
0610                      it->getNbinsX() * sizeof(float));
0611         break;
0612       case MonitorElement::Kind::TH1S:
0613         currentSubfolder.AddBinsS(it->getNbinsX(), getEmptyMetric(it->getTH1S()->GetArray(), it->getTH1S()->fN, 0, 0));
0614         curr->update(it->getNbinsX(),
0615                      getEmptyMetric(it->getTH1S()->GetArray(), it->getTH1S()->fN, 0, 0),
0616                      it->getNbinsX() * sizeof(short));
0617         break;
0618       case MonitorElement::Kind::TH1D:
0619         currentSubfolder.AddBinsD(it->getNbinsX(), getEmptyMetric(it->getTH1D()->GetArray(), it->getTH1D()->fN, 0, 0));
0620         curr->update(it->getNbinsX(),
0621                      getEmptyMetric(it->getTH1D()->GetArray(), it->getTH1D()->fN, 0, 0),
0622                      it->getNbinsX() * sizeof(double));
0623         break;
0624       case MonitorElement::Kind::TH1I:
0625         currentSubfolder.AddBinsI(it->getNbinsX(), getEmptyMetric(it->getTH1I()->GetArray(), it->getTH1I()->fN, 0, 0));
0626         curr->update(it->getNbinsX(),
0627                      getEmptyMetric(it->getTH1I()->GetArray(), it->getTH1I()->fN, 0, 0),
0628                      it->getNbinsX() * sizeof(int));
0629         break;
0630       case MonitorElement::Kind::TPROFILE:
0631         currentSubfolder.AddBinsD(it->getNbinsX(),
0632                                   getEmptyMetric(it->getTProfile()->GetArray(), it->getTProfile()->fN, 0, 0));
0633         curr->update(it->getNbinsX(),
0634                      getEmptyMetric(it->getTProfile()->GetArray(), it->getTProfile()->fN, 0, 0),
0635                      it->getNbinsX() * sizeof(double));
0636         break;
0637 
0638         // two-dim ME
0639       case MonitorElement::Kind::TH2F:
0640         currentSubfolder.AddBinsF(
0641             it->getNbinsX() * it->getNbinsY(),
0642             getEmptyMetric(it->getTH2F()->GetArray(), it->getNbinsX() + 2, it->getNbinsY() + 2, 0));
0643         curr->update(it->getNbinsX() * it->getNbinsY(),
0644                      getEmptyMetric(it->getTH2F()->GetArray(), it->getNbinsX() + 2, it->getNbinsY() + 2, 0),
0645                      it->getNbinsX() * it->getNbinsY() * sizeof(float));
0646         break;
0647       case MonitorElement::Kind::TH2S:
0648         currentSubfolder.AddBinsS(
0649             it->getNbinsX() * it->getNbinsY(),
0650             getEmptyMetric(it->getTH2S()->GetArray(), it->getNbinsX() + 2, it->getNbinsY() + 2, 0));
0651         curr->update(it->getNbinsX() * it->getNbinsY(),
0652                      getEmptyMetric(it->getTH2S()->GetArray(), it->getNbinsX() + 2, it->getNbinsY() + 2, 0),
0653                      it->getNbinsX() * it->getNbinsY() * sizeof(short));
0654         break;
0655       case MonitorElement::Kind::TH2D:
0656         currentSubfolder.AddBinsD(
0657             it->getNbinsX() * it->getNbinsY(),
0658             getEmptyMetric(it->getTH2D()->GetArray(), it->getNbinsX() + 2, it->getNbinsY() + 2, 0));
0659         curr->update(it->getNbinsX() * it->getNbinsY(),
0660                      getEmptyMetric(it->getTH2D()->GetArray(), it->getNbinsX() + 2, it->getNbinsY() + 2, 0),
0661                      it->getNbinsX() * it->getNbinsY() * sizeof(double));
0662         break;
0663       case MonitorElement::Kind::TH2I:
0664         currentSubfolder.AddBinsI(
0665             it->getNbinsX() * it->getNbinsY(),
0666             getEmptyMetric(it->getTH2I()->GetArray(), it->getNbinsX() + 2, it->getNbinsY() + 2, 0));
0667         curr->update(it->getNbinsX() * it->getNbinsY(),
0668                      getEmptyMetric(it->getTH2I()->GetArray(), it->getNbinsX() + 2, it->getNbinsY() + 2, 0),
0669                      it->getNbinsX() * it->getNbinsY() * sizeof(int));
0670         break;
0671       case MonitorElement::Kind::TPROFILE2D:
0672         currentSubfolder.AddBinsD(
0673             it->getNbinsX() * it->getNbinsY(),
0674             getEmptyMetric(it->getTProfile2D()->GetArray(), it->getNbinsX() + 2, it->getNbinsY() + 2, 0));
0675         curr->update(it->getNbinsX() * it->getNbinsY(),
0676                      getEmptyMetric(it->getTProfile2D()->GetArray(), it->getNbinsX() + 2, it->getNbinsY() + 2, 0),
0677                      it->getNbinsX() * it->getNbinsY() * sizeof(double));
0678         break;
0679 
0680         // three-dim ME
0681       case MonitorElement::Kind::TH3F:
0682         currentSubfolder.AddBinsF(
0683             it->getNbinsX() * it->getNbinsY() * it->getNbinsZ(),
0684             getEmptyMetric(it->getTH3F()->GetArray(), it->getNbinsX() + 2, it->getNbinsY() + 2, it->getNbinsZ() + 2));
0685         curr->update(
0686             it->getNbinsX() * it->getNbinsY() * it->getNbinsZ(),
0687             getEmptyMetric(it->getTH3F()->GetArray(), it->getNbinsX() + 2, it->getNbinsY() + 2, it->getNbinsZ() + 2),
0688             it->getNbinsX() * it->getNbinsY() * it->getNbinsZ() * sizeof(float));
0689         break;
0690 
0691       default: {
0692       }
0693         // here we have a DQM_KIND_INVALID, DQM_KIND_INT, DQM_KIND_REAL or DQM_KIND_STRING
0694         // which we don't care much about. Alternatively:
0695 
0696         //   std::cerr << "[DQMStoreStats::calcstats] ** WARNING: monitor element of kind: "
0697         //               << (*it)->kind() << ", name: \"" << (*it)->getName() << "\"\n"
0698         //               << "  in path: \"" << path << "\" not considered." << std::endl;
0699     }
0700   }
0701 
0702   if (mode == DQMStoreStats::considerAllME)
0703     calcIgProfDump(dbeFolder);
0704 
0705   // OUTPUT
0706 
0707   std::cout << endl;
0708   std::cout << "==========================================================================================="
0709             << std::endl;
0710   std::cout << "[DQMStoreStats::calcstats] -- Dumping stats results ";
0711   if (mode == DQMStoreStats::considerAllME)
0712     std::cout << "FOR ALL ME" << std::endl;
0713   else if (mode == DQMStoreStats::considerOnlyLumiProductME)
0714     std::cout << "FOR LUMI PRODUCTS ONLY" << std::endl;
0715   std::cout << "==========================================================================================="
0716             << std::endl;
0717   std::cout << endl;
0718 
0719   std::cout << "------------------------------------------------------------------------------------------"
0720             << std::endl;
0721   std::cout << "Configuration:" << std::endl;
0722   std::cout << "------------------------------------------------------------------------------------------"
0723             << std::endl;
0724   std::cout << " > running ";
0725   if (runonendrun_)
0726     std::cout << "on run end." << std::endl;
0727   if (runonendlumi_)
0728     std::cout << "on lumi end." << std::endl;
0729   if (runonendjob_)
0730     std::cout << "on job end." << std::endl;
0731   if (runineventloop_)
0732     std::cout << "in event loop." << std::endl;
0733   std::cout << " > pathNameMatch = \"" << pathnamematch_ << "\"" << std::endl;
0734   std::cout << std::endl;
0735 
0736   // dump folder structure
0737   std::cout << "------------------------------------------------------------------------------------------"
0738             << std::endl;
0739   std::cout << "Top level folder tree:" << std::endl;
0740   std::cout << "------------------------------------------------------------------------------------------"
0741             << std::endl;
0742   for (auto it0 = dqmStoreStatsTopLevel.begin(); it0 < dqmStoreStatsTopLevel.end(); ++it0) {
0743     std::cout << it0->subsystemName_ << " (subsystem)" << std::endl;
0744 
0745     for (auto it1 = it0->begin(); it1 < it0->end(); ++it1) {
0746       std::cout << "  |--> " << it1->subfolderName_ << " (subfolder)" << std::endl;
0747     }
0748   }
0749 
0750   // dump mem/bin table
0751 
0752   unsigned int overallNHistograms = 0, overallNBins = 0, overallNEmptyBins = 0, overallNBytes = 0;
0753 
0754   std::cout << std::endl;
0755   std::cout << "------------------------------------------------------------------------------------------"
0756             << std::endl;
0757   std::cout << "Detailed ressource usage information ";
0758   if (mode == DQMStoreStats::considerAllME)
0759     std::cout << "FOR ALL ME" << std::endl;
0760   else if (mode == DQMStoreStats::considerOnlyLumiProductME)
0761     std::cout << "FOR LUMI PRODUCTS ONLY" << std::endl;
0762   std::cout << "------------------------------------------------------------------------------------------"
0763             << std::endl;
0764   std::cout << "subsystem/folder                          histograms       bins        Empty bins     Empty/Total      "
0765                "bins per       MB         kB per"
0766             << std::endl;
0767   std::cout << "                                           (total)        (total)        (total)                      "
0768                "histogram     (total)    histogram  "
0769             << std::endl;
0770   std::cout << "------------------------------------------------------------------------------------------"
0771             << std::endl;
0772   for (auto it0 = dqmStoreStatsTopLevel.begin(); it0 < dqmStoreStatsTopLevel.end(); ++it0) {
0773     std::cout << it0->subsystemName_ << std::endl;
0774 
0775     unsigned int nHistograms = 0, nBins = 0, nEmptyBins = 0, nBytes = 0;
0776 
0777     for (auto it1 = it0->begin(); it1 < it0->end(); ++it1) {
0778       // fixed-size working copy
0779       std::string thisSubfolderName(it1->subfolderName_);
0780       if (thisSubfolderName.size() > 30) {
0781         thisSubfolderName.resize(30);
0782         thisSubfolderName.replace(thisSubfolderName.size() - 3, 3, 3, '.');
0783       }
0784 
0785       std::cout << " -> " << std::setw(30) << std::left << thisSubfolderName;
0786       std::cout << std::setw(14) << std::right << it1->totalHistos_;
0787       std::cout << std::setw(14) << std::right << it1->totalBins_;
0788       std::cout << std::setw(14) << std::right << it1->totalEmptyBins_;
0789       std::cout << std::setw(14) << std::right << std::setprecision(3)
0790                 << (float)it1->totalEmptyBins_ / (float)it1->totalBins_;
0791 
0792       // bins/histogram, need to catch nan if histos=0
0793       if (it1->totalHistos_) {
0794         std::cout << std::setw(14) << std::right << std::setprecision(3) << it1->totalBins_ / float(it1->totalHistos_);
0795       } else
0796         std::cout << std::setw(14) << std::right << "-";
0797 
0798       std::cout << std::setw(14) << std::right << std::setprecision(3) << it1->totalMemory_ / 1024. / 1024.;
0799 
0800       // mem/histogram, need to catch nan if histos=0
0801       if (it1->totalHistos_) {
0802         std::cout << std::setw(14) << std::right << std::setprecision(3)
0803                   << it1->totalMemory_ / 1024. / it1->totalHistos_;
0804       } else
0805         std::cout << std::setw(14) << std::right << "-";
0806 
0807       std::cout << std::endl;
0808 
0809       // collect totals
0810       nHistograms += it1->totalHistos_;
0811       nBins += it1->totalBins_;
0812       nEmptyBins += it1->totalEmptyBins_;
0813       nBytes += it1->totalMemory_;
0814     }
0815 
0816     overallNHistograms += nHistograms;
0817     overallNBins += nBins;
0818     overallNEmptyBins += nEmptyBins;
0819     overallNBytes += nBytes;
0820 
0821     // display totals
0822     std::cout << "    " << std::setw(30) << std::left << "SUBSYSTEM TOTAL";
0823     std::cout << std::setw(14) << std::right << nHistograms;
0824     std::cout << std::setw(14) << std::right << nBins;
0825     std::cout << std::setw(14) << std::right << nEmptyBins;
0826     std::cout << std::setw(14) << std::right << (float)nEmptyBins / (float)nBins;
0827     std::cout << std::setw(14) << std::right << std::setprecision(3) << nBins / float(nHistograms);
0828     std::cout << std::setw(14) << std::right << std::setprecision(3) << nBytes / 1024. / 1000.;
0829     std::cout << std::setw(14) << std::right << std::setprecision(3) << nBytes / 1024. / nHistograms;
0830     std::cout << std::endl;
0831 
0832     std::cout << ".........................................................................................."
0833               << std::endl;
0834   }
0835 
0836   // dump total
0837   std::cout << std::endl;
0838   std::cout << "------------------------------------------------------------------------------------------"
0839             << std::endl;
0840   std::cout << "Grand total ";
0841   if (mode == DQMStoreStats::considerAllME)
0842     std::cout << "FOR ALL ME:" << std::endl;
0843   else if (mode == DQMStoreStats::considerOnlyLumiProductME)
0844     std::cout << "FOR LUMI PRODUCTS ONLY:" << std::endl;
0845   std::cout << "------------------------------------------------------------------------------------------"
0846             << std::endl;
0847   std::cout << "Number of subsystems: " << dqmStoreStatsTopLevel.size() << std::endl;
0848   std::cout << "Total number of histograms: " << overallNHistograms << " with: " << overallNBins << " bins alltogether"
0849             << std::endl;
0850   std::cout << "Total memory occupied by histograms (excl. overhead): " << overallNBytes / 1024. / 1000. << " MB"
0851             << std::endl;
0852 
0853   std::cout << endl;
0854   std::cout << "==========================================================================================="
0855             << std::endl;
0856   std::cout << "[DQMStoreStats::calcstats] -- End of output ";
0857   if (mode == DQMStoreStats::considerAllME)
0858     std::cout << "FOR ALL ME." << std::endl;
0859   else if (mode == DQMStoreStats::considerOnlyLumiProductME)
0860     std::cout << "FOR LUMI PRODUCTS ONLY." << std::endl;
0861   std::cout << "==========================================================================================="
0862             << std::endl;
0863   std::cout << endl;
0864 
0865   // Put together a simplified version of the complete dump that is
0866   // sent to std::cout. Just dump the very basic information,
0867   // i.e. summary for each folder, both for run and LS products.
0868   if (dumpToFWJR_) {
0869     edm::Service<edm::JobReport> jr;
0870     // Do not even try if the FWJR service is not available.
0871     if (!jr.isAvailable())
0872       return 0;
0873     // Prepare appropriate map to store FWJR output.
0874     std::map<std::string, std::string> jrInfo;
0875     unsigned int overallNHistograms = 0, overallNBins = 0, overallNBytes = 0;
0876 
0877     jrInfo["Source"] = "DQMServices/Components";
0878     jrInfo["FileClass"] = "DQMStoreStats";
0879     if (runonendrun_)
0880       jrInfo["DumpType"] = "EndRun";
0881     if (runonendlumi_)
0882       jrInfo["DumpType"] = "EndLumi";
0883     if (runonendjob_)
0884       jrInfo["DumpType"] = "EndJob";
0885     if (runineventloop_)
0886       jrInfo["DumpType"] = "EventLoop";
0887     if (mode == DQMStoreStats::considerAllME)
0888       jrInfo["Type"] = "RunProduct";
0889     else if (mode == DQMStoreStats::considerOnlyLumiProductME)
0890       jrInfo["Type"] = "LumiProduct";
0891 
0892     jrInfo["pathNameMatch"] = pathnamematch_;
0893 
0894     for (auto it0 = dqmStoreStatsTopLevel.begin(); it0 < dqmStoreStatsTopLevel.end(); ++it0) {
0895       unsigned int nHistograms = 0, nBins = 0, nEmptyBins = 0, nBytes = 0;
0896       for (auto it1 = it0->begin(); it1 < it0->end(); ++it1) {
0897         // collect totals
0898         nHistograms += it1->totalHistos_;
0899         nBins += it1->totalBins_;
0900         nEmptyBins += it1->totalEmptyBins_;
0901         nBytes += it1->totalMemory_;
0902       }
0903       overallNHistograms += nHistograms;
0904       overallNBins += nBins;
0905       overallNBytes += nBytes;
0906       std::stringstream iss("");
0907       iss << nHistograms;
0908       jrInfo[it0->subsystemName_ + std::string("_h")] = iss.str();
0909       iss.str("");
0910       iss << nBins;
0911       jrInfo[it0->subsystemName_ + std::string("_b")] = iss.str();
0912       iss.str("");
0913       iss << nEmptyBins;
0914       jrInfo[it0->subsystemName_ + std::string("_be")] = iss.str();
0915       iss.str("");
0916       iss << ((float)nEmptyBins / (float)nBins);
0917       jrInfo[it0->subsystemName_ + std::string("_fbe")] = iss.str();
0918       iss.str("");
0919       iss << ((float)nBins / (float)nHistograms);
0920       jrInfo[it0->subsystemName_ + std::string("_b_h")] = iss.str();
0921       iss.str("");
0922       iss << nBytes / 1024. / 1024.;
0923       jrInfo[it0->subsystemName_ + std::string("_MB")] = iss.str();
0924       iss.str("");
0925       iss << nBytes / 1024. / nHistograms;
0926       jrInfo[it0->subsystemName_ + std::string("_Kb_h")] = iss.str();
0927     }
0928     jr->reportAnalysisFile("DQMStatsReport", jrInfo);
0929   }
0930 
0931   return 0;
0932 }
0933 
0934 ///
0935 ///
0936 ///
0937 void DQMStoreStats::dumpMemoryProfile() {
0938   std::cout << std::endl;
0939   std::cout << "------------------------------------------------------------------------------------------"
0940             << std::endl;
0941   std::cout << "Memory profile:" << std::endl;
0942   std::cout << "------------------------------------------------------------------------------------------"
0943             << std::endl;
0944 
0945   // determine virtual memory maximum
0946   std::pair<time_t, unsigned int> maxItem(0, 0);
0947   for (auto it = memoryHistoryVector_.begin(); it < memoryHistoryVector_.end(); ++it) {
0948     if (it->second > maxItem.second) {
0949       maxItem = *it;
0950     }
0951   }
0952 
0953   std::stringstream rootOutputFileName;
0954   rootOutputFileName << "dqmStoreStats_memProfile_" << getpid() << ".root";
0955 
0956   // dump memory history to root file
0957   if (dumpMemHistory_ && isOpenProcFileSuccessful_) {
0958     TFile outputFile(rootOutputFileName.str().c_str(), "RECREATE");
0959 
0960     int aTime;
0961     float aMb;
0962 
0963     TTree memHistoryTree("dqmstorestats_memhistory", "memory history");
0964     memHistoryTree.Branch("seconds", &aTime, "seconds/I");
0965     memHistoryTree.Branch("megabytes", &aMb, "megabytes/F");
0966     for (auto it = memoryHistoryVector_.begin(); it < memoryHistoryVector_.end(); ++it) {
0967       aTime = it->first - startingTime_;
0968       aMb = it->second / 1000.;
0969       memHistoryTree.Fill();
0970     }
0971 
0972     outputFile.Write();
0973     outputFile.Close();
0974   }
0975 
0976   std::cout << "Approx. maximum total virtual memory size of job: ";
0977   if (isOpenProcFileSuccessful_ && !memoryHistoryVector_.empty()) {
0978     std::cout << maxItem.second / 1000. << " MB (reached " << maxItem.first - startingTime_
0979               << " sec. after constructor called)," << std::endl;
0980     std::cout << " memory history written to: " << rootOutputFileName.str() << " (" << memoryHistoryVector_.size()
0981               << " samples)" << std::endl;
0982   } else {
0983     std::cout << "(could not be determined)" << std::endl;
0984   }
0985 
0986   std::cout << std::endl << std::endl;
0987 }
0988 
0989 ///
0990 ///
0991 ///
0992 void DQMStoreStats::print() {
0993   // subsystem info printout
0994   std::cout << " ---------- " << subsystem_ << " ---------- " << std::endl;
0995   std::cout << "  " << subfolder_ << ": ";
0996   std::cout << nmesubsys_ << " histograms with " << nbinssubsys_ << " bins. ";
0997   if (nmesubsys_ > 0)
0998     std::cout << nbinssubsys_ / nmesubsys_ << " bins/histogram ";
0999   std::cout << std::endl;
1000   std::cout << "  Largest histogram: " << maxbinsmesubsys_ << " with " << maxbinssubsys_ << " bins." << std::endl;
1001 }
1002 
1003 ///
1004 /// read virtual memory size from /proc/<pid>/status file
1005 ///
1006 std::pair<unsigned int, unsigned int> DQMStoreStats::readMemoryEntry() const {
1007   // see if initial test reading was successful
1008   if (isOpenProcFileSuccessful_) {
1009     std::ifstream procFile(procFileName_.str().c_str(), ios::in);
1010 
1011     std::string readBuffer("");
1012     unsigned int memSize = 0;
1013 
1014     // scan procfile
1015     while (!procFile.eof()) {
1016       procFile >> readBuffer;
1017       if (std::string("VmSize:") == readBuffer) {
1018         procFile >> memSize;
1019         break;
1020       }
1021     }
1022 
1023     procFile.close();
1024     return std::pair<time_t, unsigned int>(time(nullptr), memSize);
1025   }
1026 
1027   return std::pair<time_t, unsigned int>(0, 0);
1028 }
1029 
1030 //==================================================================//
1031 //========================= beginJob ===============================//
1032 //==================================================================//
1033 void DQMStoreStats::beginJob() {
1034   ////---- get DQM store interface
1035   dbe_ = Service<DQMStore>().operator->();
1036 
1037   // access the proc/ folder for memory information
1038   procFileName_ << "/proc/" << getpid() << "/status";
1039 
1040   // open for a test
1041   std::ifstream procFile(procFileName_.str().c_str(), ios::in);
1042 
1043   if (procFile.good()) {
1044     isOpenProcFileSuccessful_ = true;
1045   } else {
1046     std::cerr << " [DQMStoreStats::beginJob] ** WARNING: could not open file: " << procFileName_.str() << std::endl;
1047     std::cerr << "  Total memory profile will not be available." << std::endl;
1048     isOpenProcFileSuccessful_ = false;
1049   }
1050 
1051   procFile.close();
1052 }
1053 
1054 //==================================================================//
1055 //========================= beginRun ===============================//
1056 //==================================================================//
1057 void DQMStoreStats::beginRun(const edm::Run& r, const EventSetup& context) {}
1058 
1059 //==================================================================//
1060 //==================== analyse (takes each event) ==================//
1061 //==================================================================//
1062 void DQMStoreStats::analyze(const Event& iEvent, const EventSetup& iSetup) {
1063   //now read virtual memory size from proc folder
1064   memoryHistoryVector_.emplace_back(readMemoryEntry());
1065 
1066   if (runineventloop_) {
1067     calcstats(DQMStoreStats::considerAllME);
1068     calcstats(DQMStoreStats::considerOnlyLumiProductME);
1069     dumpMemoryProfile();
1070   }
1071 }
1072 
1073 //==================================================================//
1074 //========================= endLuminosityBlock =====================//
1075 //==================================================================//
1076 void DQMStoreStats::endLuminosityBlock(const LuminosityBlock& lumiSeg, const EventSetup& context) {
1077   if (runonendlumi_) {
1078     calcstats(DQMStoreStats::considerAllME);
1079     calcstats(DQMStoreStats::considerOnlyLumiProductME);
1080     dumpMemoryProfile();
1081   }
1082 }
1083 
1084 //==================================================================//
1085 //======================= beginLuminosityBlock =====================//
1086 //==================================================================//
1087 void DQMStoreStats::beginLuminosityBlock(const edm::LuminosityBlock& lumiSeg, const edm::EventSetup& context) {}
1088 
1089 //==================================================================//
1090 //============================= endRun =============================//
1091 //==================================================================//
1092 void DQMStoreStats::endRun(const Run& r, const EventSetup& context) {
1093   if (runonendrun_) {
1094     calcstats(DQMStoreStats::considerAllME);
1095     calcstats(DQMStoreStats::considerOnlyLumiProductME);
1096     dumpMemoryProfile();
1097   }
1098 }
1099 
1100 //==================================================================//
1101 //============================= endJob =============================//
1102 //==================================================================//
1103 void DQMStoreStats::endJob() {
1104   if (runonendjob_) {
1105     calcstats(DQMStoreStats::considerAllME);
1106     calcstats(DQMStoreStats::considerOnlyLumiProductME);
1107     dumpMemoryProfile();
1108   }
1109 }
1110 
1111 #include "FWCore/PluginManager/interface/ModuleDef.h"
1112 #include "FWCore/Framework/interface/MakerMacros.h"
1113 DEFINE_FWK_MODULE(DQMStoreStats);