Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-10-23 22:48:06

0001 // -*- C++ -*-
0002 //
0003 // Package:     PerfTools/AllocMonitor
0004 // Class  :     EventProcessingAllocMonitor
0005 //
0006 // Implementation:
0007 //     [Notes on implementation]
0008 //
0009 // Original Author:  Christopher Jones
0010 //         Created:  Mon, 21 Aug 2023 20:31:57 GMT
0011 //
0012 
0013 // system include files
0014 #include <atomic>
0015 
0016 // user include files
0017 #include "PerfTools/AllocMonitor/interface/AllocMonitorBase.h"
0018 #include "PerfTools/AllocMonitor/interface/AllocMonitorRegistry.h"
0019 #include "FWCore/Framework/interface/ComponentDescription.h"
0020 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0021 #include "FWCore/ServiceRegistry/interface/ServiceRegistry.h"
0022 #include "FWCore/ServiceRegistry/interface/ServiceMaker.h"
0023 #include "FWCore/ServiceRegistry/interface/ModuleCallingContext.h"
0024 #include "DataFormats/Provenance/interface/ModuleDescription.h"
0025 
0026 #include "moduleAlloc_setupFile.h"
0027 #include "ThreadAllocInfo.h"
0028 
0029 namespace {
0030   using namespace edm::service::moduleAlloc;
0031   class MonitorAdaptor : public cms::perftools::AllocMonitorBase {
0032   public:
0033     static void startOnThread() { threadAllocInfo().reset(); }
0034     static ThreadAllocInfo const& stopOnThread() {
0035       auto& t = threadAllocInfo();
0036       if (not t.active_) {
0037         t.reset();
0038       } else {
0039         t.deactivate();
0040       }
0041       return t;
0042     }
0043 
0044   private:
0045     static ThreadAllocInfo& threadAllocInfo() {
0046       thread_local ThreadAllocInfo s_info;
0047       return s_info;
0048     }
0049     void allocCalled(size_t iRequested, size_t iActual, void const*) final {
0050       auto& allocInfo = threadAllocInfo();
0051       if (not allocInfo.active_) {
0052         return;
0053       }
0054       allocInfo.nAllocations_ += 1;
0055       allocInfo.requested_ += iRequested;
0056 
0057       if (allocInfo.maxSingleAlloc_ < iRequested) {
0058         allocInfo.maxSingleAlloc_ = iRequested;
0059       }
0060 
0061       allocInfo.presentActual_ += iActual;
0062       if (allocInfo.presentActual_ > static_cast<long long>(allocInfo.maxActual_)) {
0063         allocInfo.maxActual_ = allocInfo.presentActual_;
0064       }
0065     }
0066     void deallocCalled(size_t iActual, void const*) final {
0067       auto& allocInfo = threadAllocInfo();
0068       if (not allocInfo.active_) {
0069         return;
0070       }
0071 
0072       allocInfo.nDeallocations_ += 1;
0073       allocInfo.presentActual_ -= iActual;
0074       if (allocInfo.presentActual_ < 0) {
0075         if (allocInfo.minActual_ == 0 or allocInfo.minActual_ > allocInfo.presentActual_) {
0076           allocInfo.minActual_ = allocInfo.presentActual_;
0077         }
0078       }
0079     }
0080   };
0081 
0082 }  // namespace
0083 
0084 namespace edm::service::moduleAlloc {
0085   Filter::Filter(std::vector<int> const* moduleIDs) : moduleIDs_{moduleIDs} {}
0086 
0087   bool Filter::startOnThread(int moduleID) const {
0088     if (not globalKeep_.load()) {
0089       return false;
0090     }
0091     if (keepModuleInfo(moduleID)) {
0092       MonitorAdaptor::startOnThread();
0093       return true;
0094     }
0095     return false;
0096   }
0097 
0098   const ThreadAllocInfo* Filter::stopOnThread(int moduleID) const {
0099     if (not globalKeep_.load()) {
0100       return nullptr;
0101     }
0102 
0103     if (keepModuleInfo(moduleID)) {
0104       return &MonitorAdaptor::stopOnThread();
0105     }
0106     return nullptr;
0107   }
0108 
0109   bool Filter::startOnThread() const {
0110     if (not globalKeep_.load()) {
0111       return false;
0112     }
0113     MonitorAdaptor::startOnThread();
0114     return true;
0115   }
0116 
0117   const ThreadAllocInfo* Filter::stopOnThread() const {
0118     if (not globalKeep_.load()) {
0119       return nullptr;
0120     }
0121     return &MonitorAdaptor::stopOnThread();
0122   }
0123 
0124   void Filter::setGlobalKeep(bool iShouldKeep) { globalKeep_.store(iShouldKeep); }
0125 
0126   bool Filter::keepModuleInfo(int moduleID) const {
0127     if ((nullptr == moduleIDs_) or (moduleIDs_->empty()) or
0128         (std::binary_search(moduleIDs_->begin(), moduleIDs_->end(), moduleID))) {
0129       return true;
0130     }
0131     return false;
0132   }
0133 }  // namespace edm::service::moduleAlloc
0134 
0135 class ModuleAllocMonitor {
0136 public:
0137   ModuleAllocMonitor(edm::ParameterSet const& iPS, edm::ActivityRegistry& iAR)
0138       : moduleNames_(iPS.getUntrackedParameter<std::vector<std::string>>("moduleNames")),
0139         nEventsToSkip_(iPS.getUntrackedParameter<unsigned int>("nEventsToSkip")),
0140         filter_(&moduleIDs_) {
0141     (void)cms::perftools::AllocMonitorRegistry::instance().createAndRegisterMonitor<MonitorAdaptor>();
0142 
0143     if (nEventsToSkip_ > 0) {
0144       filter_.setGlobalKeep(false);
0145     }
0146     if (not moduleNames_.empty()) {
0147       iAR.watchPreModuleConstruction([this](auto const& description) {
0148         auto found = std::find(moduleNames_.begin(), moduleNames_.end(), description.moduleLabel());
0149         if (found != moduleNames_.end()) {
0150           moduleIDs_.push_back(description.id());
0151           std::sort(moduleIDs_.begin(), moduleIDs_.end());
0152         }
0153       });
0154 
0155       iAR.watchPostESModuleRegistration([this](auto const& iDescription) {
0156         auto label = iDescription.label_;
0157         if (label.empty()) {
0158           label = iDescription.type_;
0159         }
0160         auto found = std::find(moduleNames_.begin(), moduleNames_.end(), label);
0161         if (found != moduleNames_.end()) {
0162           //NOTE: we want the id to start at 1 not 0
0163           moduleIDs_.push_back(-1 * (iDescription.id_ + 1));
0164           std::sort(moduleIDs_.begin(), moduleIDs_.end());
0165         }
0166       });
0167     }
0168     if (nEventsToSkip_ > 0) {
0169       iAR.watchPreSourceEvent([this](auto) {
0170         ++nEventsStarted_;
0171         if (nEventsStarted_ > nEventsToSkip_) {
0172           filter_.setGlobalKeep(true);
0173         }
0174       });
0175     }
0176     edm::service::moduleAlloc::setupFile(iPS.getUntrackedParameter<std::string>("fileName"), iAR, &filter_);
0177   }
0178 
0179   static void fillDescriptions(edm::ConfigurationDescriptions& iDesc) {
0180     edm::ParameterSetDescription ps;
0181     ps.addUntracked<std::string>("fileName");
0182     ps.addUntracked<std::vector<std::string>>("moduleNames", std::vector<std::string>());
0183     ps.addUntracked<unsigned int>("nEventsToSkip", 0);
0184     iDesc.addDefault(ps);
0185   }
0186 
0187 private:
0188   bool forThisModule(unsigned int iID) {
0189     return (moduleNames_.empty() or std::binary_search(moduleIDs_.begin(), moduleIDs_.end(), iID));
0190   }
0191   std::vector<std::string> moduleNames_;
0192   std::vector<int> moduleIDs_;
0193   unsigned int nEventsToSkip_ = 0;
0194   std::atomic<unsigned int> nEventsStarted_{0};
0195   edm::service::moduleAlloc::Filter filter_;
0196 };
0197 
0198 DEFINE_FWK_SERVICE(ModuleAllocMonitor);