File indexing completed on 2024-04-06 12:13:05
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #include "FWCore/Services/plugins/ProcInfoFetcher.h"
0017 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0018 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0019 #include "FWCore/ServiceRegistry/interface/ActivityRegistry.h"
0020 #include "FWCore/Utilities/interface/CPUTimer.h"
0021 #include "FWCore/ServiceRegistry/interface/ServiceMaker.h"
0022 #include "FWCore/ServiceRegistry/interface/SystemBounds.h"
0023
0024 namespace edm {
0025 class Event;
0026 class EventSetup;
0027
0028 namespace service {
0029 class ResourceEnforcer {
0030 public:
0031 ResourceEnforcer(edm::ParameterSet const& iConfig, edm::ActivityRegistry& iAR);
0032
0033 static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
0034
0035 private:
0036 void check();
0037 void postEventProcessing(edm::StreamContext const&);
0038
0039 ProcInfoFetcher m_fetcher;
0040 CPUTimer m_timer;
0041
0042 double m_maxVSize;
0043 double m_maxRSS;
0044 double m_maxTime;
0045 unsigned int m_nEventsToSkip;
0046 std::atomic<unsigned int> m_eventCount;
0047 std::atomic<bool> m_doingCheck;
0048 };
0049 }
0050 }
0051
0052 using namespace edm::service;
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064 ResourceEnforcer::ResourceEnforcer(edm::ParameterSet const& iConfig, ActivityRegistry& iReg)
0065 : m_maxVSize(iConfig.getUntrackedParameter<double>("maxVSize", 0) * 1000.),
0066 m_maxRSS(iConfig.getUntrackedParameter<double>("maxRSS", 0) * 1000.),
0067 m_maxTime(iConfig.getUntrackedParameter<double>("maxTime", 0) * 60. * 60.),
0068 m_nEventsToSkip(0),
0069 m_eventCount(0),
0070 m_doingCheck(false) {
0071 iReg.watchPostEvent(this, &ResourceEnforcer::postEventProcessing);
0072 iReg.watchPreallocate([this](edm::service::SystemBounds const& iBounds) {
0073
0074
0075 m_nEventsToSkip = iBounds.maxNumberOfStreams() - 1;
0076 });
0077 m_timer.start();
0078 }
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088 void ResourceEnforcer::postEventProcessing(StreamContext const&) {
0089
0090 auto count = ++m_eventCount;
0091 if (count > m_nEventsToSkip) {
0092 bool expected = false;
0093 if (m_doingCheck.compare_exchange_strong(expected, true, std::memory_order_acq_rel)) {
0094 this->check();
0095 m_doingCheck.store(false, std::memory_order_release);
0096 m_eventCount.store(0, std::memory_order_release);
0097 }
0098 }
0099 }
0100
0101 void ResourceEnforcer::check() {
0102 ProcInfo pi = m_fetcher.fetch();
0103
0104 if (0 != m_maxVSize && m_maxVSize < pi.vsize) {
0105 throw edm::Exception(errors::ExceededResourceVSize)
0106 << "Exceeded maximum allowed VSize of " << m_maxVSize / 1000. << " GB (VSize is " << pi.vsize / 1000. << ")";
0107 }
0108
0109 if (0 != m_maxRSS && m_maxRSS < pi.rss) {
0110 throw edm::Exception(errors::ExceededResourceRSS)
0111 << "Exceeded maximum allowed RSS of " << m_maxRSS / 1000. << " GB (VSize is " << pi.rss / 1000. << ")";
0112 }
0113
0114 if (0 != m_maxTime && m_maxTime < m_timer.realTime()) {
0115 throw edm::Exception(errors::ExceededResourceTime)
0116 << "Exceeded maximum allowed time of " << m_maxTime / 60. / 60. << " hours";
0117 }
0118 }
0119
0120
0121
0122
0123
0124 void ResourceEnforcer::fillDescriptions(ConfigurationDescriptions& descriptions) {
0125 ParameterSetDescription desc;
0126 desc.addUntracked<double>("maxVSize", 0.)
0127 ->setComment("Maximum allowed VSize for the job in GB. Ignored if set to 0.");
0128 desc.addUntracked<double>("maxRSS", 0.)->setComment("Maximum allowd RSS for the job in GB. Ignored if set to 0.");
0129 desc.addUntracked<double>("maxTime", 0.)
0130 ->setComment("Maximum allowd wallclock time for the job in hours. Ignored if set to 0.");
0131 descriptions.add("ResourceEnforcer", desc);
0132 }
0133
0134 DEFINE_FWK_SERVICE(ResourceEnforcer);