/
githubmirror
/
cmssw
Обзор
Документация
Войти
/
githubmirror
/
cmssw
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
FWCore/Services/plugins/Timing.cc
635 строк
28 KB
W. David Dagenhart
Remove SubProcess related code from Timing Service
29 апр 2025, 20:51
29 апр 2025, 20:51
f9cb8af
Код
Авторство
О чём код?
// -*- C++ -*- // // Package: Services // Class : Timing // /**\class edm::service::Timing */ // // Implementation: // // Original Author: Jim Kowalkowski // #include "DataFormats/Provenance/interface/ModuleDescription.h" #include "FWCore/AbstractServices/interface/TimingServiceBase.h" #include "FWCore/Framework/interface/EventSetupRecordKey.h" #include "FWCore/MessageLogger/interface/JobReport.h" #include "FWCore/MessageLogger/interface/MessageLogger.h" #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h" #include "FWCore/ParameterSet/interface/ParameterSet.h" #include "FWCore/ParameterSet/interface/ParameterSetDescription.h" #include "FWCore/ServiceRegistry/interface/ActivityRegistry.h" #include "FWCore/ServiceRegistry/interface/ESModuleCallingContext.h" #include "FWCore/ServiceRegistry/interface/GlobalContext.h" #include "FWCore/ServiceRegistry/interface/ModuleCallingContext.h" #include "FWCore/ServiceRegistry/interface/Service.h" #include "FWCore/ServiceRegistry/interface/ServiceMaker.h" #include "FWCore/ServiceRegistry/interface/ServiceRegistryfwd.h" #include "FWCore/ServiceRegistry/interface/StreamContext.h" #include "FWCore/ServiceRegistry/interface/SystemBounds.h" #include "FWCore/Utilities/interface/thread_safety_macros.h" #include "FWCore/Utilities/interface/LuminosityBlockIndex.h" #include "FWCore/Utilities/interface/RunIndex.h" #include "FWCore/Utilities/interface/StreamID.h" #include <atomic> #include <chrono> #include <map> #include <memory> #include <ratio> #include <sstream> #include <string> #include <sys/resource.h> #include <utility> #include <vector> namespace edm { namespace eventsetup { struct ComponentDescription; } // namespace eventsetup namespace service { class Timing : public TimingServiceBase { public: using time_point = std::chrono::steady_clock::time_point; using double_seconds = std::chrono::duration<double, std::ratio<1, 1>>; Timing(ParameterSet const&, ActivityRegistry&); ~Timing() override; static void fillDescriptions(edm::ConfigurationDescriptions& descriptions); void addToCPUTime(double iTime) override; double getTotalCPU() const override; private: void beginProcessing(); void postEndJob(); void preEvent(StreamContext const&); void postEvent(StreamContext const&); void postModuleEvent(StreamContext const&, ModuleCallingContext const&); void preSourceEvent(StreamID); void postSourceEvent(StreamID); void preSourceLumi(LuminosityBlockIndex); void postSourceLumi(LuminosityBlockIndex); void preSourceRun(RunIndex); void postSourceRun(RunIndex); void preOpenFile(std::string const&); void postOpenFile(std::string const&); void preModule(ModuleDescription const&); void postModule(ModuleDescription const&); void preModuleGlobal(GlobalContext const&, ModuleCallingContext const&); void postModuleGlobal(GlobalContext const&, ModuleCallingContext const&); void postGlobalBeginRun(GlobalContext const&); void postGlobalBeginLumi(GlobalContext const&); void preModuleStream(StreamContext const&, ModuleCallingContext const&); void postModuleStream(StreamContext const&, ModuleCallingContext const&); double postCommon() const; void setTaskCallbacks(ActivityRegistry&); inline void addTask() { runningTasksChanged(true); } inline void removeTask() { runningTasksChanged(false); } void runningTasksChanged(bool iMoreTasks); time_point curr_job_time_; double curr_job_cpu_; // seconds std::atomic<double> extra_job_cpu_; //seconds //use last run time for determining end of processing std::atomic<time_point> end_loop_time_; std::atomic<double> end_loop_cpu_; std::vector<time_point> curr_events_time_; bool summary_only_; bool report_summary_; double threshold_; std::atomic<bool> updating_task_info_ = false; CMS_THREAD_GUARD(updating_task_info_) unsigned int num_running_tasks_ = 0; CMS_THREAD_GUARD(updating_task_info_) time_point last_task_change_time_ = time_point(); CMS_THREAD_GUARD(updating_task_info_) double total_time_without_tasks_ = 0; // // Min Max and total event times for each Stream. // Used for summary at end of job std::vector<double> max_events_time_; // seconds std::vector<double> min_events_time_; // seconds std::vector<double> sum_events_time_; std::atomic<unsigned long> total_event_count_; std::atomic<unsigned long> begin_lumi_count_; std::atomic<unsigned long> begin_run_count_; unsigned int nStreams_; unsigned int nThreads_; std::vector<std::unique_ptr<std::atomic<time_point>>> eventSetupModuleStartTimes_; std::vector<std::pair<uintptr_t, eventsetup::EventSetupRecordKey>> eventSetupModuleCallInfo_; std::atomic<double> accumulatedEventSetupModuleTimings_ = 0.; //seconds }; } // namespace service } // namespace edm namespace edm { namespace service { static std::string d2str(double d) { std::stringstream t; t << d; return t.str(); } static std::string ui2str(unsigned int i) { std::stringstream t; t << i; return t.str(); } static std::chrono::steady_clock::time_point getTime() { return std::chrono::steady_clock::now(); } static double getChildrenCPU() { struct rusage usage; getrusage(RUSAGE_CHILDREN, &usage); double totalCPUTime = (double)usage.ru_utime.tv_sec + (double(usage.ru_utime.tv_usec) * 1E-6); totalCPUTime += (double)usage.ru_stime.tv_sec + (double(usage.ru_stime.tv_usec) * 1E-6); return totalCPUTime; } static double getCPU() { struct rusage usage; getrusage(RUSAGE_SELF, &usage); double totalCPUTime = 0.0; // User code totalCPUTime = (double)usage.ru_utime.tv_sec + (double(usage.ru_utime.tv_usec) * 1E-6); // System functions totalCPUTime += (double)usage.ru_stime.tv_sec + (double(usage.ru_stime.tv_usec) * 1E-6); // Additionally, add in CPU usage from our child processes. getrusage(RUSAGE_CHILDREN, &usage); totalCPUTime += (double)usage.ru_utime.tv_sec + (double(usage.ru_utime.tv_usec) * 1E-6); totalCPUTime += (double)usage.ru_stime.tv_sec + (double(usage.ru_stime.tv_usec) * 1E-6); return totalCPUTime; } //NOTE: We use a per thread stack for module times since unscheduled // exectuion or tbb task spawning can cause a module to run on the // same thread as an already running module static std::vector<std::chrono::steady_clock::time_point>& moduleTimeStack() { static thread_local std::vector<std::chrono::steady_clock::time_point> s_stack; return s_stack; } static double popStack() { auto& modStack = moduleTimeStack(); assert(!modStack.empty()); auto curr_module_time = modStack.back(); modStack.pop_back(); std::chrono::duration<double, std::ratio<1, 1>> t = getTime() - curr_module_time; return t.count(); } static void pushStack() { auto& modStack = moduleTimeStack(); modStack.push_back(getTime()); } Timing::Timing(ParameterSet const& iPS, ActivityRegistry& iRegistry) : curr_job_time_(), curr_job_cpu_(0.), extra_job_cpu_(0.0), end_loop_time_(), end_loop_cpu_(0.0), curr_events_time_(), summary_only_(iPS.getUntrackedParameter<bool>("summaryOnly")), report_summary_(iPS.getUntrackedParameter<bool>("useJobReport")), threshold_(iPS.getUntrackedParameter<double>("excessiveTimeThreshold")), max_events_time_(), min_events_time_(), total_event_count_(0), begin_lumi_count_(0), begin_run_count_(0) { iRegistry.watchBeginProcessing(this, &Timing::beginProcessing); iRegistry.watchPreEndJob([this]() { end_loop_time_ = getTime(); end_loop_cpu_ = getCPU(); }); iRegistry.watchPostEndJob(this, &Timing::postEndJob); iRegistry.watchPreEvent(this, &Timing::preEvent); iRegistry.watchPostEvent(this, &Timing::postEvent); bool checkThreshold = true; if (threshold_ <= 0.0) { //we need to ignore the threshold check threshold_ = std::numeric_limits<double>::max(); checkThreshold = false; } if ((not summary_only_) || (checkThreshold)) { iRegistry.watchPreModuleEvent(this, &Timing::preModuleStream); iRegistry.watchPostModuleEvent(this, &Timing::postModuleEvent); iRegistry.watchPreModuleEventAcquire(this, &Timing::preModuleStream); iRegistry.watchPostModuleEventAcquire(this, &Timing::postModuleEvent); } if (checkThreshold) { iRegistry.watchPreSourceEvent(this, &Timing::preSourceEvent); iRegistry.watchPostSourceEvent(this, &Timing::postSourceEvent); iRegistry.watchPreSourceLumi(this, &Timing::preSourceLumi); iRegistry.watchPostSourceLumi(this, &Timing::postSourceLumi); iRegistry.watchPreSourceRun(this, &Timing::preSourceRun); iRegistry.watchPostSourceRun(this, &Timing::postSourceRun); iRegistry.watchPreOpenFile(this, &Timing::preOpenFile); iRegistry.watchPostOpenFile(this, &Timing::postOpenFile); iRegistry.watchPreEventReadFromSource(this, &Timing::preModuleStream); iRegistry.watchPostEventReadFromSource(this, &Timing::postModuleStream); iRegistry.watchPreModuleConstruction(this, &Timing::preModule); iRegistry.watchPostModuleConstruction(this, &Timing::postModule); iRegistry.watchPreModuleDestruction(this, &Timing::preModule); iRegistry.watchPostModuleDestruction(this, &Timing::postModule); iRegistry.watchPreModuleBeginJob(this, &Timing::preModule); iRegistry.watchPostModuleBeginJob(this, &Timing::postModule); iRegistry.watchPreModuleEndJob(this, &Timing::preModule); iRegistry.watchPostModuleEndJob(this, &Timing::postModule); iRegistry.watchPreModuleStreamBeginRun(this, &Timing::preModuleStream); iRegistry.watchPostModuleStreamBeginRun(this, &Timing::postModuleStream); iRegistry.watchPreModuleStreamEndRun(this, &Timing::preModuleStream); iRegistry.watchPostModuleStreamEndRun(this, &Timing::postModuleStream); iRegistry.watchPreModuleStreamBeginLumi(this, &Timing::preModuleStream); iRegistry.watchPostModuleStreamBeginLumi(this, &Timing::postModuleStream); iRegistry.watchPreModuleStreamEndLumi(this, &Timing::preModuleStream); iRegistry.watchPostModuleStreamEndLumi(this, &Timing::postModuleStream); iRegistry.watchPreModuleGlobalBeginRun(this, &Timing::preModuleGlobal); iRegistry.watchPostModuleGlobalBeginRun(this, &Timing::postModuleGlobal); iRegistry.watchPreModuleGlobalEndRun(this, &Timing::preModuleGlobal); iRegistry.watchPostModuleGlobalEndRun(this, &Timing::postModuleGlobal); iRegistry.watchPreModuleGlobalBeginLumi(this, &Timing::preModuleGlobal); iRegistry.watchPostModuleGlobalBeginLumi(this, &Timing::postModuleGlobal); iRegistry.watchPreModuleGlobalEndLumi(this, &Timing::preModuleGlobal); iRegistry.watchPostModuleGlobalEndLumi(this, &Timing::postModuleGlobal); iRegistry.watchPreSourceConstruction(this, &Timing::preModule); iRegistry.watchPostSourceConstruction(this, &Timing::postModule); } auto preESModuleLambda = [this](auto const& recordKey, auto const& context) { addTask(); //find available slot auto startTime = getTime(); bool foundSlot = false; do { for (size_t i = 0; i < eventSetupModuleStartTimes_.size(); ++i) { auto& slot = *eventSetupModuleStartTimes_[i]; std::chrono::steady_clock::time_point expect; if (slot.compare_exchange_strong(expect, startTime)) { foundSlot = true; eventSetupModuleCallInfo_[i].first = uintptr_t(context.componentDescription()); eventSetupModuleCallInfo_[i].second = recordKey; break; } } //if foundSlot == false then other threads stole the slots before this thread // so should check starting over again } while (not foundSlot); }; iRegistry.watchPreESModule(preESModuleLambda); iRegistry.watchPreESModuleAcquire(preESModuleLambda); auto postESModuleLambda = [this](auto const& recordKey, auto const& context) { removeTask(); auto stopTime = getTime(); for (size_t i = 0; i < eventSetupModuleStartTimes_.size(); ++i) { auto const& info = eventSetupModuleCallInfo_[i]; if (info.first == uintptr_t(context.componentDescription()) and info.second == recordKey) { auto startTime = eventSetupModuleStartTimes_[i]->exchange(std::chrono::steady_clock::time_point()); auto expect = accumulatedEventSetupModuleTimings_.load(); double_seconds timeDiff = stopTime - startTime; auto accumulatedTime = expect + timeDiff.count(); while (not accumulatedEventSetupModuleTimings_.compare_exchange_strong(expect, accumulatedTime)) { accumulatedTime = expect + timeDiff.count(); } break; } } }; iRegistry.watchPostESModule(postESModuleLambda); iRegistry.watchPostESModuleAcquire(postESModuleLambda); iRegistry.watchPostGlobalBeginRun(this, &Timing::postGlobalBeginRun); iRegistry.watchPostGlobalBeginLumi(this, &Timing::postGlobalBeginLumi); iRegistry.watchPreallocate([this](service::SystemBounds const& iBounds) { nStreams_ = iBounds.maxNumberOfStreams(); nThreads_ = iBounds.maxNumberOfThreads(); curr_events_time_.resize(nStreams_, time_point()); sum_events_time_.resize(nStreams_, 0.); max_events_time_.resize(nStreams_, 0.); min_events_time_.resize(nStreams_, 1.E6); eventSetupModuleStartTimes_.reserve(nThreads_); for (unsigned int i = 0; i < nThreads_; ++i) { eventSetupModuleStartTimes_.emplace_back(std::make_unique<std::atomic<time_point>>()); } eventSetupModuleCallInfo_.resize(nThreads_); }); setTaskCallbacks(iRegistry); } void Timing::setTaskCallbacks(ActivityRegistry& iRegistry) { iRegistry.watchPreSourceEvent([this](auto) { addTask(); }); iRegistry.watchPostSourceEvent([this](auto) { removeTask(); }); iRegistry.watchPreModuleEvent([this](auto, auto) { addTask(); }); iRegistry.watchPostModuleEvent([this](auto, auto) { removeTask(); }); iRegistry.watchPreModuleEventAcquire([this](auto, auto) { addTask(); }); iRegistry.watchPostModuleEventAcquire([this](auto, auto) { removeTask(); }); iRegistry.watchPreSourceLumi([this](auto) { addTask(); }); iRegistry.watchPostSourceLumi([this](auto) { removeTask(); }); iRegistry.watchPreSourceRun([this](auto) { addTask(); }); iRegistry.watchPostSourceRun([this](auto) { removeTask(); }); iRegistry.watchPreEventReadFromSource([this](auto, auto) { addTask(); }); iRegistry.watchPostEventReadFromSource([this](auto, auto) { removeTask(); }); iRegistry.watchPreModuleStreamBeginRun([this](auto, auto) { addTask(); }); iRegistry.watchPostModuleStreamBeginRun([this](auto, auto) { removeTask(); }); iRegistry.watchPreModuleStreamEndRun([this](auto, auto) { addTask(); }); iRegistry.watchPostModuleStreamEndRun([this](auto, auto) { removeTask(); }); iRegistry.watchPreModuleStreamBeginLumi([this](auto, auto) { addTask(); }); iRegistry.watchPostModuleStreamBeginLumi([this](auto, auto) { removeTask(); }); iRegistry.watchPreModuleStreamEndLumi([this](auto, auto) { addTask(); }); iRegistry.watchPostModuleStreamEndLumi([this](auto, auto) { removeTask(); }); iRegistry.watchPreModuleGlobalBeginRun([this](auto, auto) { addTask(); }); iRegistry.watchPostModuleGlobalBeginRun([this](auto, auto) { removeTask(); }); iRegistry.watchPreModuleGlobalEndRun([this](auto, auto) { addTask(); }); iRegistry.watchPostModuleGlobalEndRun([this](auto, auto) { removeTask(); }); iRegistry.watchPreModuleGlobalBeginLumi([this](auto, auto) { addTask(); }); iRegistry.watchPostModuleGlobalBeginLumi([this](auto, auto) { removeTask(); }); iRegistry.watchPreModuleGlobalEndLumi([this](auto, auto) { addTask(); }); iRegistry.watchPostModuleGlobalEndLumi([this](auto, auto) { removeTask(); }); //account for any time ESSources spend looking up new IOVs iRegistry.watchPreESSyncIOV([this](auto const&) { addTask(); }); iRegistry.watchPostESSyncIOV([this](auto const&) { removeTask(); }); } Timing::~Timing() {} void Timing::addToCPUTime(double iTime) { //For accounting purposes we effectively can say we started earlier double expected = extra_job_cpu_.load(); while (not extra_job_cpu_.compare_exchange_strong(expected, expected + iTime)) { } } double Timing::getTotalCPU() const { return getCPU(); } void Timing::fillDescriptions(ConfigurationDescriptions& descriptions) { ParameterSetDescription desc; desc.addUntracked<bool>("summaryOnly", false)->setComment("If 'true' do not report timing for each event"); desc.addUntracked<bool>("useJobReport", true)->setComment("If 'true' write summary information to JobReport"); desc.addUntracked<double>("excessiveTimeThreshold", 0.) ->setComment( "Amount of time in seconds before reporting a module or source has taken excessive time. A value of 0.0 " "turns off this reporting."); descriptions.add("Timing", desc); descriptions.setComment("This service reports the time it takes to run each module in a job."); } void Timing::beginProcessing() { curr_job_time_ = getTime(); curr_job_cpu_ = getCPU(); last_task_change_time_ = curr_job_time_; if (not summary_only_) { LogImportant("TimeReport") << "TimeReport> Report activated" << "\n" << "TimeReport> Report columns headings for events: " << "eventnum runnum timetaken\n" << "TimeReport> Report columns headings for modules: " << "eventnum runnum modulelabel modulename timetaken\n" << "TimeReport> JobTime=" << std::chrono::time_point_cast<std::chrono::seconds>(curr_job_time_).time_since_epoch().count() << " JobCPU=" << curr_job_cpu_ << "\n"; } } void Timing::postEndJob() { const auto job_end_time = getTime(); const double job_end_cpu = getCPU(); auto total_job_time = double_seconds(job_end_time - jobStartTime()).count(); double total_job_cpu = job_end_cpu + extra_job_cpu_; const double job_end_children_cpu = getChildrenCPU(); const double total_initialization_time = double_seconds(curr_job_time_ - jobStartTime()).count(); const double total_initialization_cpu = curr_job_cpu_; if (time_point() == jobStartTime()) { //did not capture beginning time total_job_time = double_seconds(job_end_time - curr_job_time_).count(); total_job_cpu = job_end_cpu + extra_job_cpu_ - curr_job_cpu_; } double min_event_time = *(std::min_element(min_events_time_.begin(), min_events_time_.end())); double max_event_time = *(std::max_element(max_events_time_.begin(), max_events_time_.end())); auto total_loop_time = double_seconds(end_loop_time_.load() - curr_job_time_).count(); auto total_loop_cpu = end_loop_cpu_ + extra_job_cpu_ - curr_job_cpu_; if (end_loop_time_.load() == time_point()) { total_loop_time = 0.0; total_loop_cpu = 0.0; } double sum_all_events_time = 0; for (auto t : sum_events_time_) { sum_all_events_time += t; } double average_event_time = 0.0; if (total_event_count_ != 0) { average_event_time = sum_all_events_time / total_event_count_; } double event_throughput = 0.0; if (total_loop_time != 0.0) { event_throughput = total_event_count_ / total_loop_time; } LogImportant("TimeReport") << "TimeReport> Time report complete in " << total_job_time << " seconds" << "\n" << " Time Summary: \n" << " - Min event: " << min_event_time << "\n" << " - Max event: " << max_event_time << "\n" << " - Avg event: " << average_event_time << "\n" << " - Total loop: " << total_loop_time << "\n" << " - Total init: " << total_initialization_time << "\n" << " - Total job: " << total_job_time << "\n" << " - Total EventSetup: " << accumulatedEventSetupModuleTimings_.load() << "\n" << " - Total non-module: " << total_time_without_tasks_ << "\n" << " Event Throughput: " << event_throughput << " ev/s\n" << " CPU Summary: \n" << " - Total loop: " << total_loop_cpu << "\n" << " - Total init: " << total_initialization_cpu << "\n" << " - Total extra: " << extra_job_cpu_ << "\n" << " - Total children: " << job_end_children_cpu << "\n" << " - Total job: " << total_job_cpu << "\n" << " Processing Summary: \n" << " - Number of Events: " << total_event_count_ << "\n" << " - Number of Global Begin Lumi Calls: " << begin_lumi_count_ << "\n" << " - Number of Global Begin Run Calls: " << begin_run_count_ << "\n"; if (report_summary_) { Service<JobReport> reportSvc; std::map<std::string, std::string> reportData; reportData.insert(std::make_pair("MinEventTime", d2str(min_event_time))); reportData.insert(std::make_pair("MaxEventTime", d2str(max_event_time))); reportData.insert(std::make_pair("AvgEventTime", d2str(average_event_time))); reportData.insert(std::make_pair("EventThroughput", d2str(event_throughput))); reportData.insert(std::make_pair("TotalJobTime", d2str(total_job_time))); reportData.insert(std::make_pair("TotalJobCPU", d2str(total_job_cpu))); reportData.insert(std::make_pair("TotalJobChildrenCPU", d2str(job_end_children_cpu))); reportData.insert(std::make_pair("TotalLoopTime", d2str(total_loop_time))); reportData.insert(std::make_pair("TotalEventSetupTime", d2str(accumulatedEventSetupModuleTimings_.load()))); reportData.insert(std::make_pair("TotalNonModuleTime", d2str(total_time_without_tasks_))); reportData.insert(std::make_pair("TotalLoopCPU", d2str(total_loop_cpu))); reportData.insert(std::make_pair("TotalInitTime", d2str(total_initialization_time))); reportData.insert(std::make_pair("TotalInitCPU", d2str(total_initialization_cpu))); reportData.insert(std::make_pair("NumberOfStreams", ui2str(nStreams_))); reportData.insert(std::make_pair("NumberOfThreads", ui2str(nThreads_))); reportSvc->reportPerformanceSummary("Timing", reportData); std::map<std::string, std::string> reportData1; reportData1.insert(std::make_pair("NumberEvents", ui2str(total_event_count_))); reportData1.insert(std::make_pair("NumberBeginLumiCalls", ui2str(begin_lumi_count_))); reportData1.insert(std::make_pair("NumberBeginRunCalls", ui2str(begin_run_count_))); reportSvc->reportPerformanceSummary("ProcessingSummary", reportData1); } } void Timing::preEvent(StreamContext const& iStream) { auto index = iStream.streamID().value(); curr_events_time_[index] = getTime(); } void Timing::postEvent(StreamContext const& iStream) { auto index = iStream.streamID().value(); std::chrono::steady_clock::duration curr_event_time = getTime() - curr_events_time_[index]; double curr_event_time_d = double_seconds(curr_event_time).count(); sum_events_time_[index] += curr_event_time_d; if (not summary_only_) { auto const& eventID = iStream.eventID(); LogPrint("TimeEvent") << "TimeEvent> " << eventID.event() << " " << eventID.run() << " " << curr_event_time_d; } if (curr_event_time_d > max_events_time_[index]) max_events_time_[index] = curr_event_time_d; if (curr_event_time_d < min_events_time_[index]) min_events_time_[index] = curr_event_time_d; ++total_event_count_; } void Timing::postModuleEvent(StreamContext const& iStream, ModuleCallingContext const& iModule) { auto const& eventID = iStream.eventID(); auto const& desc = *(iModule.moduleDescription()); double t = postCommon(); if (not summary_only_) { LogPrint("TimeModule") << "TimeModule> " << eventID.event() << " " << eventID.run() << " " << desc.moduleLabel() << " " << desc.moduleName() << " " << t; } } void Timing::preSourceEvent(StreamID) { pushStack(); } void Timing::postSourceEvent(StreamID) { postCommon(); } void Timing::preSourceLumi(LuminosityBlockIndex) { pushStack(); } void Timing::postSourceLumi(LuminosityBlockIndex) { postCommon(); } void Timing::preSourceRun(RunIndex) { pushStack(); } void Timing::postSourceRun(RunIndex) { postCommon(); } void Timing::preOpenFile(std::string const&) { pushStack(); } void Timing::postOpenFile(std::string const&) { postCommon(); } void Timing::preModule(ModuleDescription const&) { pushStack(); } void Timing::postModule(ModuleDescription const&) { postCommon(); } void Timing::preModuleGlobal(GlobalContext const&, ModuleCallingContext const&) { pushStack(); } void Timing::postModuleGlobal(GlobalContext const&, ModuleCallingContext const& mcc) { postCommon(); } void Timing::postGlobalBeginRun(GlobalContext const& gc) { ++begin_run_count_; } void Timing::postGlobalBeginLumi(GlobalContext const& gc) { ++begin_lumi_count_; } void Timing::preModuleStream(StreamContext const&, ModuleCallingContext const&) { pushStack(); } void Timing::postModuleStream(StreamContext const&, ModuleCallingContext const& mcc) { postCommon(); } double Timing::postCommon() const { double t = popStack(); if (t > threshold_) { LogError("ExcessiveTime") << "ExcessiveTime: Module used " << t << " seconds of time which exceeds the error threshold configured in the Timing Service of " << threshold_ << " seconds."; } return t; } void Timing::runningTasksChanged(bool iMoreTasks) { const auto presentTime = getTime(); bool expected = false; while (not updating_task_info_.compare_exchange_strong(expected, true)) { expected = false; } auto previousNumberOfTasks = iMoreTasks ? num_running_tasks_++ : num_running_tasks_--; total_time_without_tasks_ += (nThreads_ - previousNumberOfTasks) * double_seconds(presentTime - last_task_change_time_).count(); last_task_change_time_ = presentTime; updating_task_info_ = false; } } // namespace service } // namespace edm using edm::service::Timing; typedef edm::serviceregistry::AllArgsMaker<edm::TimingServiceBase, Timing> TimingMaker; DEFINE_FWK_SERVICE_MAKER(Timing, TimingMaker);