CMS 3D CMS Logo

PeriodicAllocMonitor.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: PerfTools/AllocMonitor
4 // Class : PeriodicAllocMonitor
5 //
6 // Implementation:
7 // [Notes on implementation]
8 //
9 // Original Author: Christopher Jones
10 // Created: Fri, 15 Sep 2023 14:44:38 GMT
11 //
12 
13 // system include files
14 #include <thread>
15 #include <chrono>
16 #include <fstream>
17 
18 // user include files
26 
27 namespace {
28  class MonitorAdaptor : public cms::perftools::AllocMonitorBase {
29  public:
30  struct Report {
31  size_t requested_;
32  size_t presentActual_;
33  size_t maxActual_;
34  size_t nAllocations_;
35  size_t nDeallocations_;
36  size_t maxSingleRequested_;
37  };
38  Report report() const {
39  Report report;
40  report.requested_ = requested_.load(std::memory_order_acquire);
41  report.maxActual_ = maxActual_.load(std::memory_order_acquire);
42  report.presentActual_ = presentActual_.load(std::memory_order_acquire);
43  report.nAllocations_ = nAllocations_.load(std::memory_order_acquire);
44  report.nDeallocations_ = nDeallocations_.load(std::memory_order_acquire);
45  report.maxSingleRequested_ = maxSingleRequested_.load(std::memory_order_acquire);
46 
47  return report;
48  }
49 
50  private:
51  void allocCalled(size_t iRequested, size_t iActual) final {
52  nAllocations_.fetch_add(1, std::memory_order_acq_rel);
53  requested_.fetch_add(iRequested, std::memory_order_acq_rel);
54 
55  //returns previous value
56  auto a = presentActual_.fetch_add(iActual, std::memory_order_acq_rel);
57  a += iActual;
58 
59  auto max = maxActual_.load(std::memory_order_relaxed);
60  while (a > max) {
61  if (maxActual_.compare_exchange_strong(max, a, std::memory_order_acq_rel)) {
62  break;
63  }
64  }
65 
66  auto single = maxSingleRequested_.load(std::memory_order_relaxed);
67  while (iRequested > single) {
68  if (maxSingleRequested_.compare_exchange_strong(single, iRequested, std::memory_order_acq_rel)) {
69  break;
70  }
71  }
72  }
73  void deallocCalled(size_t iActual) final {
74  if (0 == iActual)
75  return;
76  nDeallocations_.fetch_add(1, std::memory_order_acq_rel);
77  auto present = presentActual_.load(std::memory_order_acquire);
78  if (present >= iActual) {
79  presentActual_.fetch_sub(iActual, std::memory_order_acq_rel);
80  }
81  }
82 
83  std::atomic<size_t> requested_ = 0;
84  std::atomic<size_t> presentActual_ = 0;
85  std::atomic<size_t> maxActual_ = 0;
86  std::atomic<size_t> nAllocations_ = 0;
87  std::atomic<size_t> nDeallocations_ = 0;
88  std::atomic<size_t> maxSingleRequested_ = 0;
89  };
90 
91 } // namespace
92 
94 public:
97  auto fileName = iPS.getUntrackedParameter<std::string>("filename");
98  auto interval = iPS.getUntrackedParameter<unsigned long long>("millisecondsPerMeasurement");
99 
100  threadShutDown_ = false;
101  thread_ = std::thread([this, fileName, interval, adaptor]() {
102  auto const start = std::chrono::steady_clock::now();
103  std::ofstream fs(fileName);
104  fs << "timestamp, runs-started, lumis-started, events-started, events-finished, total-requested, max-actual, "
105  "present-actual, max-single, nAllocs, nDeallocs\n";
106  while (continueRunning_.load()) {
107  auto rStarted = nRunsStarted_.load(std::memory_order_acquire);
108  auto lStarted = nLumisStarted_.load(std::memory_order_acquire);
109  auto const now = std::chrono::steady_clock::now();
110  auto eStarted = nEventsStarted_.load(std::memory_order_acquire);
111  auto eFinished = nEventsFinished_.load(std::memory_order_acquire);
112  auto report = adaptor->report();
113 
114  fs << std::chrono::duration_cast<std::chrono::milliseconds>(now - start).count() << ", " << rStarted << ", "
115  << lStarted << ", " << eStarted << ", " << eFinished << ", " << report.requested_ << ", "
116  << report.maxActual_ << ", " << report.presentActual_ << ", " << report.maxSingleRequested_ << ", "
117  << report.nAllocations_ << ", " << report.nDeallocations_ << std::endl;
118  std::this_thread::sleep_for(std::chrono::milliseconds(interval));
119  }
120  });
121 
122  iAR.watchPreEvent([this](auto const&) { nEventsStarted_.fetch_add(1, std::memory_order_acq_rel); });
123  iAR.watchPostEvent([this](auto const&) { nEventsFinished_.fetch_add(1, std::memory_order_acq_rel); });
124  iAR.watchPreGlobalBeginRun([this](auto const&) { nRunsStarted_.fetch_add(1, std::memory_order_acq_rel); });
125  iAR.watchPreGlobalBeginLumi([this](auto const&) { nLumisStarted_.fetch_add(1, std::memory_order_acq_rel); });
126  iAR.watchPreEndJob([adaptor, this]() {
127  continueRunning_ = false;
128  thread_.join();
129  threadShutDown_ = true;
131  });
132  }
134  if (not threadShutDown_) {
135  continueRunning_ = false;
136  thread_.join();
137  }
138  }
139 
142  ps.addUntracked<std::string>("filename", "timing.log")->setComment("Name of file to write the reports");
143  ps.addUntracked<unsigned long long>("millisecondsPerMeasurement", 1000)
144  ->setComment("The frequency at which to write reports");
145  iDesc.addDefault(ps);
146  }
147 
148 private:
149  std::thread thread_;
150  std::atomic<std::size_t> nRunsStarted_ = 0;
151  std::atomic<std::size_t> nLumisStarted_ = 0;
152  std::atomic<std::size_t> nEventsStarted_ = 0;
153  std::atomic<std::size_t> nEventsFinished_ = 0;
154  std::atomic<bool> continueRunning_ = true;
155  bool threadShutDown_ = true;
156 };
157 
Definition: start.py:1
void watchPreEvent(PreEvent::slot_type const &iSlot)
ParameterDescriptionBase * addUntracked(U const &iLabel, T const &value)
void watchPostEvent(PostEvent::slot_type const &iSlot)
void watchPreGlobalBeginLumi(PreGlobalBeginLumi::slot_type const &iSlot)
int single(int argc, char *argv[])
Definition: DMRsingle.cc:18
T getUntrackedParameter(std::string const &, T const &) const
std::atomic< std::size_t > nRunsStarted_
virtual void deallocCalled(size_t iActualSize)=0
PeriodicAllocMonitor(edm::ParameterSet const &iPS, edm::ActivityRegistry &iAR)
static AllocMonitorRegistry & instance()
void addDefault(ParameterSetDescription const &psetDescription)
virtual void allocCalled(size_t iRequestedSize, size_t iActualSize)=0
std::atomic< bool > continueRunning_
std::atomic< std::size_t > nLumisStarted_
void watchPreGlobalBeginRun(PreGlobalBeginRun::slot_type const &iSlot)
#define DEFINE_FWK_SERVICE(type)
Definition: ServiceMaker.h:97
static void fillDescriptions(edm::ConfigurationDescriptions &iDesc)
std::atomic< std::size_t > nEventsFinished_
void watchPreEndJob(PreEndJob::slot_type const &iSlot)
std::atomic< std::size_t > nEventsStarted_
double a
Definition: hdecay.h:121