|
| 1 | +// -*- C++ -*- |
| 2 | +// |
| 3 | +// Package: PerfTools/AllocMonitor |
| 4 | +// Class : EventProcessingAllocMonitor |
| 5 | +// |
| 6 | +// Implementation: |
| 7 | +// [Notes on implementation] |
| 8 | +// |
| 9 | +// Original Author: Christopher Jones |
| 10 | +// Created: Mon, 21 Aug 2023 20:31:57 GMT |
| 11 | +// |
| 12 | + |
| 13 | +// system include files |
| 14 | +#include <atomic> |
| 15 | + |
| 16 | +// user include files |
| 17 | +#include "PerfTools/AllocMonitor/interface/AllocMonitorBase.h" |
| 18 | +#include "PerfTools/AllocMonitor/interface/AllocMonitorRegistry.h" |
| 19 | +#include "FWCore/Framework/interface/ComponentDescription.h" |
| 20 | +#include "FWCore/MessageLogger/interface/MessageLogger.h" |
| 21 | +#include "FWCore/ServiceRegistry/interface/ServiceRegistry.h" |
| 22 | +#include "FWCore/ServiceRegistry/interface/ServiceMaker.h" |
| 23 | +#include "FWCore/ServiceRegistry/interface/ModuleCallingContext.h" |
| 24 | +#include "DataFormats/Provenance/interface/ModuleDescription.h" |
| 25 | + |
| 26 | +#include "moduleAlloc_setupFile.h" |
| 27 | +#include "ThreadAllocInfo.h" |
| 28 | + |
| 29 | +namespace { |
| 30 | + using namespace edm::service::moduleAlloc; |
| 31 | + class MonitorAdaptor : public cms::perftools::AllocMonitorBase { |
| 32 | + public: |
| 33 | + static void startOnThread() { threadAllocInfo().reset(); } |
| 34 | + static ThreadAllocInfo const& stopOnThread() { |
| 35 | + auto& t = threadAllocInfo(); |
| 36 | + if (not t.active_) { |
| 37 | + t.reset(); |
| 38 | + } else { |
| 39 | + t.deactivate(); |
| 40 | + } |
| 41 | + return t; |
| 42 | + } |
| 43 | + |
| 44 | + private: |
| 45 | + static ThreadAllocInfo& threadAllocInfo() { |
| 46 | + thread_local ThreadAllocInfo s_info; |
| 47 | + return s_info; |
| 48 | + } |
| 49 | + void allocCalled(size_t iRequested, size_t iActual) final { |
| 50 | + auto& allocInfo = threadAllocInfo(); |
| 51 | + if (not allocInfo.active_) { |
| 52 | + return; |
| 53 | + } |
| 54 | + allocInfo.nAllocations_ += 1; |
| 55 | + allocInfo.requested_ += iRequested; |
| 56 | + |
| 57 | + if (allocInfo.maxSingleAlloc_ < iRequested) { |
| 58 | + allocInfo.maxSingleAlloc_ = iRequested; |
| 59 | + } |
| 60 | + |
| 61 | + allocInfo.presentActual_ += iActual; |
| 62 | + if (allocInfo.presentActual_ > static_cast<long long>(allocInfo.maxActual_)) { |
| 63 | + allocInfo.maxActual_ = allocInfo.presentActual_; |
| 64 | + } |
| 65 | + } |
| 66 | + void deallocCalled(size_t iActual) final { |
| 67 | + auto& allocInfo = threadAllocInfo(); |
| 68 | + if (not allocInfo.active_) { |
| 69 | + return; |
| 70 | + } |
| 71 | + |
| 72 | + allocInfo.nDeallocations_ += 1; |
| 73 | + allocInfo.presentActual_ -= iActual; |
| 74 | + if (allocInfo.presentActual_ < 0) { |
| 75 | + if (allocInfo.minActual_ == 0 or allocInfo.minActual_ > allocInfo.presentActual_) { |
| 76 | + allocInfo.minActual_ = allocInfo.presentActual_; |
| 77 | + } |
| 78 | + } |
| 79 | + } |
| 80 | + }; |
| 81 | + |
| 82 | +} // namespace |
| 83 | + |
| 84 | +namespace edm::service::moduleAlloc { |
| 85 | + Filter::Filter(std::vector<int> const* moduleIDs) : moduleIDs_{moduleIDs} {} |
| 86 | + |
| 87 | + bool Filter::startOnThread(int moduleID) const { |
| 88 | + if (not globalKeep_.load()) { |
| 89 | + return false; |
| 90 | + } |
| 91 | + if (keepModuleInfo(moduleID)) { |
| 92 | + MonitorAdaptor::startOnThread(); |
| 93 | + return true; |
| 94 | + } |
| 95 | + return false; |
| 96 | + } |
| 97 | + |
| 98 | + const ThreadAllocInfo* Filter::stopOnThread(int moduleID) const { |
| 99 | + if (not globalKeep_.load()) { |
| 100 | + return nullptr; |
| 101 | + } |
| 102 | + |
| 103 | + if (keepModuleInfo(moduleID)) { |
| 104 | + return &MonitorAdaptor::stopOnThread(); |
| 105 | + } |
| 106 | + return nullptr; |
| 107 | + } |
| 108 | + |
| 109 | + bool Filter::startOnThread() const { |
| 110 | + if (not globalKeep_.load()) { |
| 111 | + return false; |
| 112 | + } |
| 113 | + MonitorAdaptor::startOnThread(); |
| 114 | + return true; |
| 115 | + } |
| 116 | + |
| 117 | + const ThreadAllocInfo* Filter::stopOnThread() const { |
| 118 | + if (not globalKeep_.load()) { |
| 119 | + return nullptr; |
| 120 | + } |
| 121 | + return &MonitorAdaptor::stopOnThread(); |
| 122 | + } |
| 123 | + |
| 124 | + void Filter::setGlobalKeep(bool iShouldKeep) { globalKeep_.store(iShouldKeep); } |
| 125 | + |
| 126 | + bool Filter::keepModuleInfo(int moduleID) const { |
| 127 | + if ((nullptr == moduleIDs_) or (moduleIDs_->empty()) or |
| 128 | + (std::binary_search(moduleIDs_->begin(), moduleIDs_->end(), moduleID))) { |
| 129 | + return true; |
| 130 | + } |
| 131 | + return false; |
| 132 | + } |
| 133 | +} // namespace edm::service::moduleAlloc |
| 134 | + |
| 135 | +class ModuleAllocMonitor { |
| 136 | +public: |
| 137 | + ModuleAllocMonitor(edm::ParameterSet const& iPS, edm::ActivityRegistry& iAR) |
| 138 | + : moduleNames_(iPS.getUntrackedParameter<std::vector<std::string>>("moduleNames")), |
| 139 | + nEventsToSkip_(iPS.getUntrackedParameter<unsigned int>("nEventsToSkip")), |
| 140 | + filter_(&moduleIDs_) { |
| 141 | + (void)cms::perftools::AllocMonitorRegistry::instance().createAndRegisterMonitor<MonitorAdaptor>(); |
| 142 | + |
| 143 | + if (nEventsToSkip_ > 0) { |
| 144 | + filter_.setGlobalKeep(false); |
| 145 | + } |
| 146 | + if (not moduleNames_.empty()) { |
| 147 | + iAR.watchPreModuleConstruction([this](auto const& description) { |
| 148 | + auto found = std::find(moduleNames_.begin(), moduleNames_.end(), description.moduleLabel()); |
| 149 | + if (found != moduleNames_.end()) { |
| 150 | + moduleIDs_.push_back(description.id()); |
| 151 | + std::sort(moduleIDs_.begin(), moduleIDs_.end()); |
| 152 | + } |
| 153 | + }); |
| 154 | + |
| 155 | + iAR.watchPostESModuleRegistration([this](auto const& iDescription) { |
| 156 | + auto label = iDescription.label_; |
| 157 | + if (label.empty()) { |
| 158 | + label = iDescription.type_; |
| 159 | + } |
| 160 | + auto found = std::find(moduleNames_.begin(), moduleNames_.end(), label); |
| 161 | + if (found != moduleNames_.end()) { |
| 162 | + //NOTE: we want the id to start at 1 not 0 |
| 163 | + moduleIDs_.push_back(-1 * (iDescription.id_ + 1)); |
| 164 | + std::sort(moduleIDs_.begin(), moduleIDs_.end()); |
| 165 | + } |
| 166 | + }); |
| 167 | + } |
| 168 | + if (nEventsToSkip_ > 0) { |
| 169 | + iAR.watchPreSourceEvent([this](auto) { |
| 170 | + ++nEventsStarted_; |
| 171 | + if (nEventsStarted_ > nEventsToSkip_) { |
| 172 | + filter_.setGlobalKeep(true); |
| 173 | + } |
| 174 | + }); |
| 175 | + } |
| 176 | + edm::service::moduleAlloc::setupFile(iPS.getUntrackedParameter<std::string>("fileName"), iAR, &filter_); |
| 177 | + } |
| 178 | + |
| 179 | + static void fillDescriptions(edm::ConfigurationDescriptions& iDesc) { |
| 180 | + edm::ParameterSetDescription ps; |
| 181 | + ps.addUntracked<std::string>("fileName"); |
| 182 | + ps.addUntracked<std::vector<std::string>>("moduleNames", std::vector<std::string>()); |
| 183 | + ps.addUntracked<unsigned int>("nEventsToSkip", 0); |
| 184 | + iDesc.addDefault(ps); |
| 185 | + } |
| 186 | + |
| 187 | +private: |
| 188 | + bool forThisModule(unsigned int iID) { |
| 189 | + return (moduleNames_.empty() or std::binary_search(moduleIDs_.begin(), moduleIDs_.end(), iID)); |
| 190 | + } |
| 191 | + std::vector<std::string> moduleNames_; |
| 192 | + std::vector<int> moduleIDs_; |
| 193 | + unsigned int nEventsToSkip_ = 0; |
| 194 | + std::atomic<unsigned int> nEventsStarted_{0}; |
| 195 | + edm::service::moduleAlloc::Filter filter_; |
| 196 | +}; |
| 197 | + |
| 198 | +DEFINE_FWK_SERVICE(ModuleAllocMonitor); |
0 commit comments