File indexing completed on 2023-10-25 09:57:43
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <thread>
0015 #include <chrono>
0016 #include <fstream>
0017
0018
0019 #include "PerfTools/AllocMonitor/interface/AllocMonitorBase.h"
0020 #include "PerfTools/AllocMonitor/interface/AllocMonitorRegistry.h"
0021 #include "FWCore/ServiceRegistry/interface/ServiceRegistry.h"
0022 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0023 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
0024 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0025 #include "FWCore/ServiceRegistry/interface/ServiceMaker.h"
0026
0027 namespace {
0028 class MonitorAdaptor : public cms::perftools::AllocMonitorBase {
0029 public:
0030 struct Report {
0031 size_t requested_;
0032 size_t presentActual_;
0033 size_t maxActual_;
0034 size_t nAllocations_;
0035 size_t nDeallocations_;
0036 size_t maxSingleRequested_;
0037 };
0038 Report report() const {
0039 Report report;
0040 report.requested_ = requested_.load(std::memory_order_acquire);
0041 report.maxActual_ = maxActual_.load(std::memory_order_acquire);
0042 report.presentActual_ = presentActual_.load(std::memory_order_acquire);
0043 report.nAllocations_ = nAllocations_.load(std::memory_order_acquire);
0044 report.nDeallocations_ = nDeallocations_.load(std::memory_order_acquire);
0045 report.maxSingleRequested_ = maxSingleRequested_.load(std::memory_order_acquire);
0046
0047 return report;
0048 }
0049
0050 private:
0051 void allocCalled(size_t iRequested, size_t iActual) final {
0052 nAllocations_.fetch_add(1, std::memory_order_acq_rel);
0053 requested_.fetch_add(iRequested, std::memory_order_acq_rel);
0054
0055
0056 auto a = presentActual_.fetch_add(iActual, std::memory_order_acq_rel);
0057 a += iActual;
0058
0059 auto max = maxActual_.load(std::memory_order_relaxed);
0060 while (a > max) {
0061 if (maxActual_.compare_exchange_strong(max, a, std::memory_order_acq_rel)) {
0062 break;
0063 }
0064 }
0065
0066 auto single = maxSingleRequested_.load(std::memory_order_relaxed);
0067 while (iRequested > single) {
0068 if (maxSingleRequested_.compare_exchange_strong(single, iRequested, std::memory_order_acq_rel)) {
0069 break;
0070 }
0071 }
0072 }
0073 void deallocCalled(size_t iActual) final {
0074 if (0 == iActual)
0075 return;
0076 nDeallocations_.fetch_add(1, std::memory_order_acq_rel);
0077 auto present = presentActual_.load(std::memory_order_acquire);
0078 if (present >= iActual) {
0079 presentActual_.fetch_sub(iActual, std::memory_order_acq_rel);
0080 }
0081 }
0082
0083 std::atomic<size_t> requested_ = 0;
0084 std::atomic<size_t> presentActual_ = 0;
0085 std::atomic<size_t> maxActual_ = 0;
0086 std::atomic<size_t> nAllocations_ = 0;
0087 std::atomic<size_t> nDeallocations_ = 0;
0088 std::atomic<size_t> maxSingleRequested_ = 0;
0089 };
0090
0091 }
0092
0093 class PeriodicAllocMonitor {
0094 public:
0095 PeriodicAllocMonitor(edm::ParameterSet const& iPS, edm::ActivityRegistry& iAR) {
0096 auto adaptor = cms::perftools::AllocMonitorRegistry::instance().createAndRegisterMonitor<MonitorAdaptor>();
0097 auto fileName = iPS.getUntrackedParameter<std::string>("filename");
0098 auto interval = iPS.getUntrackedParameter<unsigned long long>("millisecondsPerMeasurement");
0099
0100 threadShutDown_ = false;
0101 thread_ = std::thread([this, fileName, interval, adaptor]() {
0102 auto const start = std::chrono::steady_clock::now();
0103 std::ofstream fs(fileName);
0104 fs << "timestamp, runs-started, lumis-started, events-started, events-finished, total-requested, max-actual, "
0105 "present-actual, max-single, nAllocs, nDeallocs\n";
0106 while (continueRunning_.load()) {
0107 auto rStarted = nRunsStarted_.load(std::memory_order_acquire);
0108 auto lStarted = nLumisStarted_.load(std::memory_order_acquire);
0109 auto const now = std::chrono::steady_clock::now();
0110 auto eStarted = nEventsStarted_.load(std::memory_order_acquire);
0111 auto eFinished = nEventsFinished_.load(std::memory_order_acquire);
0112 auto report = adaptor->report();
0113
0114 fs << std::chrono::duration_cast<std::chrono::milliseconds>(now - start).count() << ", " << rStarted << ", "
0115 << lStarted << ", " << eStarted << ", " << eFinished << ", " << report.requested_ << ", "
0116 << report.maxActual_ << ", " << report.presentActual_ << ", " << report.maxSingleRequested_ << ", "
0117 << report.nAllocations_ << ", " << report.nDeallocations_ << std::endl;
0118 std::this_thread::sleep_for(std::chrono::milliseconds(interval));
0119 }
0120 });
0121
0122 iAR.watchPreEvent([this](auto const&) { nEventsStarted_.fetch_add(1, std::memory_order_acq_rel); });
0123 iAR.watchPostEvent([this](auto const&) { nEventsFinished_.fetch_add(1, std::memory_order_acq_rel); });
0124 iAR.watchPreGlobalBeginRun([this](auto const&) { nRunsStarted_.fetch_add(1, std::memory_order_acq_rel); });
0125 iAR.watchPreGlobalBeginLumi([this](auto const&) { nLumisStarted_.fetch_add(1, std::memory_order_acq_rel); });
0126 iAR.watchPreEndJob([adaptor, this]() {
0127 continueRunning_ = false;
0128 thread_.join();
0129 threadShutDown_ = true;
0130 cms::perftools::AllocMonitorRegistry::instance().deregisterMonitor(adaptor);
0131 });
0132 }
0133 ~PeriodicAllocMonitor() {
0134 if (not threadShutDown_) {
0135 continueRunning_ = false;
0136 thread_.join();
0137 }
0138 }
0139
0140 static void fillDescriptions(edm::ConfigurationDescriptions& iDesc) {
0141 edm::ParameterSetDescription ps;
0142 ps.addUntracked<std::string>("filename", "timing.log")->setComment("Name of file to write the reports");
0143 ps.addUntracked<unsigned long long>("millisecondsPerMeasurement", 1000)
0144 ->setComment("The frequency at which to write reports");
0145 iDesc.addDefault(ps);
0146 }
0147
0148 private:
0149 std::thread thread_;
0150 std::atomic<std::size_t> nRunsStarted_ = 0;
0151 std::atomic<std::size_t> nLumisStarted_ = 0;
0152 std::atomic<std::size_t> nEventsStarted_ = 0;
0153 std::atomic<std::size_t> nEventsFinished_ = 0;
0154 std::atomic<bool> continueRunning_ = true;
0155 bool threadShutDown_ = true;
0156 };
0157
0158 DEFINE_FWK_SERVICE(PeriodicAllocMonitor);