Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-12-17 02:43:53

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 #if defined(ALLOC_USE_PTHREADS)
0027 #include <pthread.h>
0028 #else
0029 #include <unistd.h>
0030 #include <sys/syscall.h>
0031 #endif
0032 
0033 #include "moduleAlloc_setupFile.h"
0034 #include "ThreadAllocInfo.h"
0035 #include "ThreadTracker.h"
0036 
0037 namespace {
0038   using namespace cms::perftools::allocMon;
0039   using namespace edm::service::moduleAlloc;
0040   class MonitorAdaptor : public cms::perftools::AllocMonitorBase {
0041   public:
0042     static void startOnThread() { threadAllocInfo().reset(); }
0043     static ThreadAllocInfo const& stopOnThread() {
0044       auto& t = threadAllocInfo();
0045       if (not t.active_) {
0046         t.reset();
0047       } else {
0048         t.deactivate();
0049       }
0050       return t;
0051     }
0052 
0053   private:
0054     static ThreadAllocInfo& threadAllocInfo() {
0055       static ThreadAllocInfo s_info[ThreadTracker::kTotalEntries];
0056       return s_info[ThreadTracker::instance().thread_index()];
0057     }
0058     void allocCalled(size_t iRequested, size_t iActual, void const*) final {
0059       auto& allocInfo = threadAllocInfo();
0060       if (not allocInfo.active_) {
0061         return;
0062       }
0063       allocInfo.nAllocations_ += 1;
0064       allocInfo.requested_ += iRequested;
0065 
0066       if (allocInfo.maxSingleAlloc_ < iRequested) {
0067         allocInfo.maxSingleAlloc_ = iRequested;
0068       }
0069 
0070       allocInfo.presentActual_ += iActual;
0071       if (allocInfo.presentActual_ > static_cast<long long>(allocInfo.maxActual_)) {
0072         allocInfo.maxActual_ = allocInfo.presentActual_;
0073       }
0074     }
0075     void deallocCalled(size_t iActual, void const*) final {
0076       auto& allocInfo = threadAllocInfo();
0077       if (not allocInfo.active_) {
0078         return;
0079       }
0080 
0081       allocInfo.nDeallocations_ += 1;
0082       allocInfo.presentActual_ -= iActual;
0083       if (allocInfo.presentActual_ < 0) {
0084         if (allocInfo.minActual_ == 0 or allocInfo.minActual_ > allocInfo.presentActual_) {
0085           allocInfo.minActual_ = allocInfo.presentActual_;
0086         }
0087       }
0088     }
0089   };
0090 
0091 }  // namespace
0092 
0093 namespace edm::service::moduleAlloc {
0094   Filter::Filter(std::vector<int> const* moduleIDs) : moduleIDs_{moduleIDs} {}
0095 
0096   bool Filter::startOnThread(int moduleID) const {
0097     if (not globalKeep_.load()) {
0098       return false;
0099     }
0100     if (keepModuleInfo(moduleID)) {
0101       MonitorAdaptor::startOnThread();
0102       return true;
0103     }
0104     return false;
0105   }
0106 
0107   const ThreadAllocInfo* Filter::stopOnThread(int moduleID) const {
0108     if (not globalKeep_.load()) {
0109       return nullptr;
0110     }
0111 
0112     if (keepModuleInfo(moduleID)) {
0113       return &MonitorAdaptor::stopOnThread();
0114     }
0115     return nullptr;
0116   }
0117 
0118   bool Filter::startOnThread() const {
0119     if (not globalKeep_.load()) {
0120       return false;
0121     }
0122     MonitorAdaptor::startOnThread();
0123     return true;
0124   }
0125 
0126   const ThreadAllocInfo* Filter::stopOnThread() const {
0127     if (not globalKeep_.load()) {
0128       return nullptr;
0129     }
0130     return &MonitorAdaptor::stopOnThread();
0131   }
0132 
0133   void Filter::setGlobalKeep(bool iShouldKeep) { globalKeep_.store(iShouldKeep); }
0134 
0135   bool Filter::keepModuleInfo(int moduleID) const {
0136     if ((nullptr == moduleIDs_) or (moduleIDs_->empty()) or
0137         (std::binary_search(moduleIDs_->begin(), moduleIDs_->end(), moduleID))) {
0138       return true;
0139     }
0140     return false;
0141   }
0142 }  // namespace edm::service::moduleAlloc
0143 
0144 class ModuleAllocMonitor {
0145 public:
0146   ModuleAllocMonitor(edm::ParameterSet const& iPS, edm::ActivityRegistry& iAR)
0147       : moduleNames_(iPS.getUntrackedParameter<std::vector<std::string>>("moduleNames")),
0148         nEventsToSkip_(iPS.getUntrackedParameter<unsigned int>("nEventsToSkip")),
0149         filter_(&moduleIDs_) {
0150     (void)cms::perftools::AllocMonitorRegistry::instance().createAndRegisterMonitor<MonitorAdaptor>();
0151 
0152     if (nEventsToSkip_ > 0) {
0153       filter_.setGlobalKeep(false);
0154     }
0155     if (not moduleNames_.empty()) {
0156       iAR.watchPreModuleConstruction([this](auto const& description) {
0157         auto found = std::find(moduleNames_.begin(), moduleNames_.end(), description.moduleLabel());
0158         if (found != moduleNames_.end()) {
0159           moduleIDs_.push_back(description.id());
0160           std::sort(moduleIDs_.begin(), moduleIDs_.end());
0161         }
0162       });
0163 
0164       iAR.watchPostESModuleRegistration([this](auto const& iDescription) {
0165         auto label = iDescription.label_;
0166         if (label.empty()) {
0167           label = iDescription.type_;
0168         }
0169         auto found = std::find(moduleNames_.begin(), moduleNames_.end(), label);
0170         if (found != moduleNames_.end()) {
0171           //NOTE: we want the id to start at 1 not 0
0172           moduleIDs_.push_back(-1 * (iDescription.id_ + 1));
0173           std::sort(moduleIDs_.begin(), moduleIDs_.end());
0174         }
0175       });
0176     }
0177     if (nEventsToSkip_ > 0) {
0178       iAR.watchPreSourceEvent([this](auto) {
0179         ++nEventsStarted_;
0180         if (nEventsStarted_ > nEventsToSkip_) {
0181           filter_.setGlobalKeep(true);
0182         }
0183       });
0184     }
0185     edm::service::moduleAlloc::setupFile(iPS.getUntrackedParameter<std::string>("fileName"), iAR, &filter_);
0186   }
0187 
0188   static void fillDescriptions(edm::ConfigurationDescriptions& iDesc) {
0189     edm::ParameterSetDescription ps;
0190     ps.addUntracked<std::string>("fileName");
0191     ps.addUntracked<std::vector<std::string>>("moduleNames", std::vector<std::string>());
0192     ps.addUntracked<unsigned int>("nEventsToSkip", 0);
0193     iDesc.addDefault(ps);
0194   }
0195 
0196 private:
0197   bool forThisModule(unsigned int iID) {
0198     return (moduleNames_.empty() or std::binary_search(moduleIDs_.begin(), moduleIDs_.end(), iID));
0199   }
0200   std::vector<std::string> moduleNames_;
0201   std::vector<int> moduleIDs_;
0202   unsigned int nEventsToSkip_ = 0;
0203   std::atomic<unsigned int> nEventsStarted_{0};
0204   edm::service::moduleAlloc::Filter filter_;
0205 };
0206 
0207 DEFINE_FWK_SERVICE(ModuleAllocMonitor);