Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-11-09 02:40:55

0001 // -*- C++ -*-
0002 //
0003 // Package:     PerfTools/MaxMemoryPreload
0004 // Class  :     preload
0005 //
0006 // Implementation:
0007 //     [Notes on implementation]
0008 //
0009 // Original Author:  Christopher Jones
0010 //         Created:  Wed, 23 Aug 2023 17:56:44 GMT
0011 //
0012 
0013 // system include files
0014 #include <atomic>
0015 #include <iostream>
0016 
0017 // user include files
0018 #include "PerfTools/AllocMonitor/interface/AllocMonitorBase.h"
0019 #include "PerfTools/AllocMonitor/interface/AllocMonitorRegistry.h"
0020 
0021 //
0022 // constants, enums and typedefs
0023 //
0024 
0025 //
0026 // static data member definitions
0027 //
0028 
0029 // Hooks the target application can be instrumented with to pause and
0030 // unpause the MaxMemoryPreload. Pausing the monitoring during a
0031 // multithreaded execution can result in unexpected results, because
0032 // the setting is global.
0033 namespace {
0034   std::atomic<bool> paused = false;
0035 }
0036 void pauseMaxMemoryPreload() { paused = true; }
0037 void unpauseMaxMemoryPreload() { paused = false; }
0038 
0039 namespace {
0040   class MonitorAdaptor : public cms::perftools::AllocMonitorBase {
0041   public:
0042     MonitorAdaptor() noexcept = default;
0043     ~MonitorAdaptor() noexcept override { performanceReport(); }
0044 
0045   private:
0046     void allocCalled(size_t iRequested, size_t iActual, void const*) final {
0047       if (paused)
0048         return;
0049 
0050       nAllocations_.fetch_add(1, std::memory_order_acq_rel);
0051       requested_.fetch_add(iRequested, std::memory_order_acq_rel);
0052 
0053       auto a = presentActual_.fetch_add(iActual, std::memory_order_acq_rel);
0054       a += iActual;
0055       auto max = maxActual_.load(std::memory_order_relaxed);
0056 
0057       while (a > max) {
0058         if (maxActual_.compare_exchange_strong(max, a, std::memory_order_acq_rel)) {
0059           break;
0060         }
0061       }
0062     }
0063     void deallocCalled(size_t iActual, void const*) final {
0064       if (paused)
0065         return;
0066 
0067       nDeallocations_.fetch_add(1, std::memory_order_acq_rel);
0068       auto present = presentActual_.load(std::memory_order_acquire);
0069       if (present >= iActual) {
0070         presentActual_.fetch_sub(iActual, std::memory_order_acq_rel);
0071       }
0072     }
0073 
0074     void performanceReport() const {
0075       auto finalRequested = requested_.load(std::memory_order_acquire);
0076       auto maxActual = maxActual_.load(std::memory_order_acquire);
0077       auto present = presentActual_.load(std::memory_order_acquire);
0078       auto allocs = nAllocations_.load(std::memory_order_acquire);
0079       auto deallocs = nDeallocations_.load(std::memory_order_acquire);
0080 
0081       std::cerr << "Memory Report: total memory requested: " << finalRequested
0082                 << "\nMemory Report:  max memory used: " << maxActual << "\nMemory Report:  presently used: " << present
0083                 << "\nMemory Report:  # allocations calls:   " << allocs
0084                 << "\nMemory Report:  # deallocations calls: " << deallocs << "\n";
0085     }
0086 
0087   private:
0088     std::atomic<size_t> requested_ = 0;
0089     std::atomic<size_t> presentActual_ = 0;
0090     std::atomic<size_t> maxActual_ = 0;
0091     std::atomic<size_t> nAllocations_ = 0;
0092     std::atomic<size_t> nDeallocations_ = 0;
0093   };
0094 
0095   [[maybe_unused]] auto const* const s_instance =
0096       cms::perftools::AllocMonitorRegistry::instance().createAndRegisterMonitor<MonitorAdaptor>();
0097 }  // namespace