CMS 3D CMS Logo

ModuleAllocMonitor.cc
Go to the documentation of this file.
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
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 
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 
136 public:
138  : moduleNames_(iPS.getUntrackedParameter<std::vector<std::string>>("moduleNames")),
139  nEventsToSkip_(iPS.getUntrackedParameter<unsigned int>("nEventsToSkip")),
140  filter_(&moduleIDs_) {
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  }
177  }
178 
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};
196 };
197 
void watchPostESModuleRegistration(PostESModuleRegistration::slot_type const &iSlot)
ParameterDescriptionBase * addUntracked(U const &iLabel, T const &value)
void watchPreModuleConstruction(PreModuleConstruction::slot_type const &iSlot)
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:19
const ThreadAllocInfo * stopOnThread() const
TEMPL(T2) struct Divides void
Definition: Factorize.h:24
T getUntrackedParameter(std::string const &, T const &) const
bool forThisModule(unsigned int iID)
Filter(std::vector< int > const *moduleIDs)
char const * label
static AllocMonitorRegistry & instance()
void setupFile(std::string const &iFileName, edm::ActivityRegistry &iRegistry, Filter const *iFilter)
void addDefault(ParameterSetDescription const &psetDescription)
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e< void, edm::EventID const &, edm::Timestamp const & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
Definition: Activities.doc:12
edm::service::moduleAlloc::Filter filter_
std::vector< int > moduleIDs_
bool keepModuleInfo(int moduleID) const
std::vector< std::string > moduleNames_
#define DEFINE_FWK_SERVICE(type)
Definition: ServiceMaker.h:97
std::vector< int > const * moduleIDs_
void watchPreSourceEvent(PreSourceEvent::slot_type const &iSlot)
ModuleAllocMonitor(edm::ParameterSet const &iPS, edm::ActivityRegistry &iAR)
static void fillDescriptions(edm::ConfigurationDescriptions &iDesc)