Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-09-12 10:07:47

0001 #ifndef FastTimerService_h
0002 #define FastTimerService_h
0003 
0004 // system headers
0005 #include <unistd.h>
0006 #include <pthread.h>
0007 
0008 // C++ headers
0009 #include <atomic>
0010 #include <chrono>
0011 #include <cmath>
0012 #include <memory>
0013 #include <mutex>
0014 #include <string>
0015 #include <vector>
0016 
0017 // boost headers
0018 #include <boost/chrono.hpp>
0019 
0020 // tbb headers
0021 #include <oneapi/tbb/concurrent_unordered_set.h>
0022 #include <oneapi/tbb/enumerable_thread_specific.h>
0023 #include <oneapi/tbb/task_scheduler_observer.h>
0024 
0025 // JSON headers
0026 #include <nlohmann/json_fwd.hpp>
0027 using json = nlohmann::json;
0028 
0029 // CMSSW headers
0030 #include "FWCore/ServiceRegistry/interface/ActivityRegistry.h"
0031 #include "FWCore/ServiceRegistry/interface/Service.h"
0032 #include "FWCore/ServiceRegistry/interface/SystemBounds.h"
0033 #include "FWCore/ServiceRegistry/interface/ModuleCallingContext.h"
0034 #include "FWCore/ServiceRegistry/interface/PathContext.h"
0035 #include "FWCore/ServiceRegistry/interface/StreamContext.h"
0036 #include "FWCore/ServiceRegistry/interface/ProcessContext.h"
0037 #include "FWCore/ServiceRegistry/interface/GlobalContext.h"
0038 #include "FWCore/ServiceRegistry/interface/ESModuleCallingContext.h"
0039 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0040 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0041 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0042 #include "DataFormats/Common/interface/HLTPathStatus.h"
0043 #include "DataFormats/Provenance/interface/ModuleDescription.h"
0044 #include "DQMServices/Core/interface/DQMStore.h"
0045 #include "HLTrigger/Timer/interface/ProcessCallGraph.h"
0046 
0047 /*
0048 procesing time is divided into
0049  - source
0050  - event processing, sum of the time spent in all the modules
0051 */
0052 
0053 class FastTimerService : public tbb::task_scheduler_observer {
0054 public:
0055   FastTimerService(const edm::ParameterSet&, edm::ActivityRegistry&);
0056   ~FastTimerService() override = default;
0057 
0058 private:
0059   void ignoredSignal(const std::string& signal) const;
0060   void unsupportedSignal(const std::string& signal) const;
0061 
0062   // these signal pairs are not guaranteed to happen in the same thread
0063 
0064   void preallocate(edm::service::SystemBounds const&);
0065 
0066   void lookupInitializationComplete(edm::PathsAndConsumesOfModulesBase const&, edm::ProcessContext const&);
0067 
0068   void postEndJob();
0069 
0070   void preGlobalBeginRun(edm::GlobalContext const&);
0071   void postGlobalBeginRun(edm::GlobalContext const&);
0072 
0073   void preGlobalEndRun(edm::GlobalContext const&);
0074   void postGlobalEndRun(edm::GlobalContext const&);
0075 
0076   void preStreamBeginRun(edm::StreamContext const&);
0077   void postStreamBeginRun(edm::StreamContext const&);
0078 
0079   void preStreamEndRun(edm::StreamContext const&);
0080   void postStreamEndRun(edm::StreamContext const&);
0081 
0082   void preGlobalBeginLumi(edm::GlobalContext const&);
0083   void postGlobalBeginLumi(edm::GlobalContext const&);
0084 
0085   void preGlobalEndLumi(edm::GlobalContext const&);
0086   void postGlobalEndLumi(edm::GlobalContext const&);
0087 
0088   void preStreamBeginLumi(edm::StreamContext const&);
0089   void postStreamBeginLumi(edm::StreamContext const&);
0090 
0091   void preStreamEndLumi(edm::StreamContext const&);
0092   void postStreamEndLumi(edm::StreamContext const&);
0093 
0094   void preEvent(edm::StreamContext const&);
0095   void postEvent(edm::StreamContext const&);
0096 
0097   void prePathEvent(edm::StreamContext const&, edm::PathContext const&);
0098   void postPathEvent(edm::StreamContext const&, edm::PathContext const&, edm::HLTPathStatus const&);
0099 
0100   void preModuleEventPrefetching(edm::StreamContext const&, edm::ModuleCallingContext const&);
0101   void postModuleEventPrefetching(edm::StreamContext const&, edm::ModuleCallingContext const&);
0102 
0103   // these signal pairs are guaranteed to be called from the same thread
0104 
0105   //void preOpenFile(std::string const&, bool);
0106   //void postOpenFile(std::string const&, bool);
0107 
0108   //void preCloseFile(std::string const&, bool);
0109   //void postCloseFile(std::string const&, bool);
0110 
0111   void preSourceConstruction(edm::ModuleDescription const&);
0112   //void postSourceConstruction(edm::ModuleDescription const&);
0113 
0114   void preSourceRun(edm::RunIndex);
0115   void postSourceRun(edm::RunIndex);
0116 
0117   void preSourceLumi(edm::LuminosityBlockIndex);
0118   void postSourceLumi(edm::LuminosityBlockIndex);
0119 
0120   void preSourceEvent(edm::StreamID);
0121   void postSourceEvent(edm::StreamID);
0122 
0123   //void preModuleConstruction(edm::ModuleDescription const&);
0124   //void postModuleConstruction(edm::ModuleDescription const&);
0125 
0126   //void preModuleBeginJob(edm::ModuleDescription const&);
0127   //void postModuleBeginJob(edm::ModuleDescription const&);
0128 
0129   //void preModuleEndJob(edm::ModuleDescription const&);
0130   //void postModuleEndJob(edm::ModuleDescription const&);
0131 
0132   //void preModuleBeginStream(edm::StreamContext const&, edm::ModuleCallingContext const&);
0133   //void postModuleBeginStream(edm::StreamContext const&, edm::ModuleCallingContext const&);
0134 
0135   //void preModuleEndStream(edm::StreamContext const&, edm::ModuleCallingContext const&);
0136   //void postModuleEndStream(edm::StreamContext const&, edm::ModuleCallingContext const&);
0137 
0138   void preModuleGlobalBeginRun(edm::GlobalContext const&, edm::ModuleCallingContext const&);
0139   void postModuleGlobalBeginRun(edm::GlobalContext const&, edm::ModuleCallingContext const&);
0140 
0141   void preModuleGlobalEndRun(edm::GlobalContext const&, edm::ModuleCallingContext const&);
0142   void postModuleGlobalEndRun(edm::GlobalContext const&, edm::ModuleCallingContext const&);
0143 
0144   void preModuleGlobalBeginLumi(edm::GlobalContext const&, edm::ModuleCallingContext const&);
0145   void postModuleGlobalBeginLumi(edm::GlobalContext const&, edm::ModuleCallingContext const&);
0146 
0147   void preModuleGlobalEndLumi(edm::GlobalContext const&, edm::ModuleCallingContext const&);
0148   void postModuleGlobalEndLumi(edm::GlobalContext const&, edm::ModuleCallingContext const&);
0149 
0150   void preModuleStreamBeginRun(edm::StreamContext const&, edm::ModuleCallingContext const&);
0151   void postModuleStreamBeginRun(edm::StreamContext const&, edm::ModuleCallingContext const&);
0152 
0153   void preModuleStreamEndRun(edm::StreamContext const&, edm::ModuleCallingContext const&);
0154   void postModuleStreamEndRun(edm::StreamContext const&, edm::ModuleCallingContext const&);
0155 
0156   void preModuleStreamBeginLumi(edm::StreamContext const&, edm::ModuleCallingContext const&);
0157   void postModuleStreamBeginLumi(edm::StreamContext const&, edm::ModuleCallingContext const&);
0158 
0159   void preModuleStreamEndLumi(edm::StreamContext const&, edm::ModuleCallingContext const&);
0160   void postModuleStreamEndLumi(edm::StreamContext const&, edm::ModuleCallingContext const&);
0161 
0162   void preModuleEventAcquire(edm::StreamContext const&, edm::ModuleCallingContext const&);
0163   void postModuleEventAcquire(edm::StreamContext const&, edm::ModuleCallingContext const&);
0164 
0165   void preModuleEvent(edm::StreamContext const&, edm::ModuleCallingContext const&);
0166   void postModuleEvent(edm::StreamContext const&, edm::ModuleCallingContext const&);
0167 
0168   void preModuleEventDelayedGet(edm::StreamContext const&, edm::ModuleCallingContext const&);
0169   void postModuleEventDelayedGet(edm::StreamContext const&, edm::ModuleCallingContext const&);
0170 
0171   void preEventReadFromSource(edm::StreamContext const&, edm::ModuleCallingContext const&);
0172   void postEventReadFromSource(edm::StreamContext const&, edm::ModuleCallingContext const&);
0173 
0174   void preESModule(edm::eventsetup::EventSetupRecordKey const&, edm::ESModuleCallingContext const&);
0175   void postESModule(edm::eventsetup::EventSetupRecordKey const&, edm::ESModuleCallingContext const&);
0176 
0177   // inherited from TBB task_scheduler_observer
0178   void on_scheduler_entry(bool worker) final;
0179   void on_scheduler_exit(bool worker) final;
0180 
0181 public:
0182   static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
0183   static void fixForDQM(std::string& label);
0184 
0185 private:
0186   // forward declarations
0187   struct Resources;
0188   struct AtomicResources;
0189 
0190   // per-thread measurements
0191   struct Measurement {
0192   public:
0193     Measurement() noexcept;
0194     // take per-thread measurements
0195     void measure() noexcept;
0196     // take per-thread measurements, compute the delta with respect to the previous measurement, and store them in the argument
0197     void measure_and_store(Resources& store) noexcept;
0198     // take per-thread measurements, compute the delta with respect to the previous measurement, and add them to the argument
0199     void measure_and_accumulate(Resources& store) noexcept;
0200     void measure_and_accumulate(AtomicResources& store) noexcept;
0201 
0202   public:
0203 #ifdef DEBUG_THREAD_CONCURRENCY
0204     std::thread::id id;
0205 #endif  // DEBUG_THREAD_CONCURRENCY
0206     boost::chrono::thread_clock::time_point time_thread;
0207     boost::chrono::high_resolution_clock::time_point time_real;
0208     uint64_t allocated;
0209     uint64_t deallocated;
0210   };
0211 
0212   // highlight a group of modules
0213   struct GroupOfModules {
0214   public:
0215     std::string label;
0216     std::vector<unsigned int> modules;
0217   };
0218 
0219   // resources being monitored by the service
0220   struct Resources {
0221   public:
0222     Resources();
0223     void reset();
0224 
0225     Resources& operator+=(Resources const& other);
0226     Resources& operator+=(struct AtomicResources const& other);
0227     Resources operator+(Resources const& other) const;
0228     Resources operator+(struct AtomicResources const& other) const;
0229 
0230   public:
0231     boost::chrono::nanoseconds time_thread;
0232     boost::chrono::nanoseconds time_real;
0233     uint64_t allocated;
0234     uint64_t deallocated;
0235   };
0236 
0237   // atomic version of Resources
0238   // Note: the structure as a whole is *not* atomic, only the individual fields are
0239   struct AtomicResources {
0240   public:
0241     AtomicResources();
0242     AtomicResources(AtomicResources const& other);
0243     void reset();
0244 
0245     AtomicResources& operator=(AtomicResources const& other);
0246     AtomicResources& operator+=(AtomicResources const& other);
0247     AtomicResources& operator+=(Resources const& other);
0248     AtomicResources operator+(AtomicResources const& other) const;
0249     Resources operator+(Resources const& other) const;
0250 
0251   public:
0252     std::atomic<boost::chrono::nanoseconds::rep> time_thread;
0253     std::atomic<boost::chrono::nanoseconds::rep> time_real;
0254     std::atomic<uint64_t> allocated;
0255     std::atomic<uint64_t> deallocated;
0256   };
0257 
0258   // resources associated to each module, path, process and job
0259 
0260   struct ResourcesPerModule {
0261   public:
0262     ResourcesPerModule() noexcept;
0263     void reset() noexcept;
0264 
0265     ResourcesPerModule& operator+=(ResourcesPerModule const& other);
0266     ResourcesPerModule operator+(ResourcesPerModule const& other) const;
0267 
0268   public:
0269     Resources total;
0270     unsigned events;
0271   };
0272 
0273   struct ResourcesPerPath {
0274   public:
0275     void reset();
0276     ResourcesPerPath& operator+=(ResourcesPerPath const& other);
0277     ResourcesPerPath operator+(ResourcesPerPath const& other) const;
0278 
0279   public:
0280     Resources active;  // resources used by all modules on this path
0281     Resources total;   // resources used by all modules on this path, and their dependencies
0282     unsigned last;     // one-past-the last module that ran on this path
0283     bool status;       // whether the path accepted or rejected the event
0284   };
0285 
0286   struct ResourcesPerProcess {
0287   public:
0288     ResourcesPerProcess() = default;
0289     ResourcesPerProcess(ProcessCallGraph::ProcessType const& process);
0290     void reset();
0291     ResourcesPerProcess& operator+=(ResourcesPerProcess const& other);
0292     ResourcesPerProcess operator+(ResourcesPerProcess const& other) const;
0293 
0294   public:
0295     Resources total;
0296     std::vector<ResourcesPerPath> paths;
0297     std::vector<ResourcesPerPath> endpaths;
0298   };
0299 
0300   struct ResourcesPerJob {
0301   public:
0302     ResourcesPerJob() = default;
0303     ResourcesPerJob(ProcessCallGraph const& job, std::vector<GroupOfModules> const& groups);
0304     void reset();
0305     ResourcesPerJob& operator+=(ResourcesPerJob const& other);
0306     ResourcesPerJob operator+(ResourcesPerJob const& other) const;
0307 
0308   public:
0309     Resources total;
0310     AtomicResources overhead;
0311     AtomicResources eventsetup;
0312     AtomicResources idle;
0313     AtomicResources source;
0314     Resources event;  // total time etc. spent between preSourceEvent and postEvent
0315     Measurement event_measurement;
0316     std::vector<Resources> highlight;
0317     std::vector<ResourcesPerModule> modules;
0318     // Before the Framework SubProcess feature was removed, the following data
0319     // member was a vector<ResourcesPerProcess>. If something like SubProcess is
0320     // implemented again in the future, it may need to become a vector again. When
0321     // SubProcess support was removed from this service, we left ResourcesPerJob
0322     // and ResourcesPerProcess as separate classes because we are considering the
0323     // possibility of reimplementing something like SubProcess and having them
0324     // separate will make that easier...
0325     ResourcesPerProcess process;
0326     unsigned events;
0327   };
0328 
0329   // plot ranges and resolution
0330   struct PlotRanges {
0331     double time_range;
0332     double time_resolution;
0333     double memory_range;
0334     double memory_resolution;
0335   };
0336 
0337   // plots associated to each module or other element (path, process, etc)
0338   class PlotsPerElement {
0339   public:
0340     PlotsPerElement() = default;
0341     void book(dqm::reco::DQMStore::IBooker&,
0342               std::string const& name,
0343               std::string const& title,
0344               PlotRanges const& ranges,
0345               unsigned int lumisections,
0346               bool byls);
0347     void fill(Resources const&, unsigned int lumisection);
0348     void fill(AtomicResources const&, unsigned int lumisection);
0349     void fill_fraction(Resources const&, Resources const&, unsigned int lumisection);
0350 
0351   private:
0352     // resources spent in the module
0353     dqm::reco::MonitorElement* time_thread_ = nullptr;       // TH1F
0354     dqm::reco::MonitorElement* time_thread_byls_ = nullptr;  // TProfile
0355     dqm::reco::MonitorElement* time_real_ = nullptr;         // TH1F
0356     dqm::reco::MonitorElement* time_real_byls_ = nullptr;    // TProfile
0357     dqm::reco::MonitorElement* allocated_ = nullptr;         // TH1F
0358     dqm::reco::MonitorElement* allocated_byls_ = nullptr;    // TProfile
0359     dqm::reco::MonitorElement* deallocated_ = nullptr;       // TH1F
0360     dqm::reco::MonitorElement* deallocated_byls_ = nullptr;  // TProfile
0361   };
0362 
0363   // plots associated to each path or endpath
0364   class PlotsPerPath {
0365   public:
0366     PlotsPerPath() = default;
0367     void book(dqm::reco::DQMStore::IBooker&,
0368               std::string const&,
0369               ProcessCallGraph const&,
0370               ProcessCallGraph::PathType const&,
0371               PlotRanges const& ranges,
0372               unsigned int lumisections,
0373               bool byls);
0374     void fill(ProcessCallGraph::PathType const&,
0375               ResourcesPerJob const&,
0376               ResourcesPerPath const&,
0377               unsigned int lumisection);
0378 
0379   private:
0380     // resources spent in all the modules in the path, including their dependencies
0381     PlotsPerElement total_;
0382 
0383     // Note:
0384     //   a TH1F has 7 significant digits, while a 24-hour long run could process
0385     //   order of 10 billion events; a 64-bit long integer would work and might
0386     //   be better suited than a double, but there is no "TH1L" in ROOT.
0387 
0388     // how many times each module and their dependencies has run
0389     dqm::reco::MonitorElement* module_counter_ = nullptr;  // TH1D
0390     // resources spent in each module and their dependencies
0391     dqm::reco::MonitorElement* module_time_thread_total_ = nullptr;  // TH1D
0392     dqm::reco::MonitorElement* module_time_real_total_ = nullptr;    // TH1D
0393     dqm::reco::MonitorElement* module_allocated_total_ = nullptr;    // TH1D
0394     dqm::reco::MonitorElement* module_deallocated_total_ = nullptr;  // TH1D
0395   };
0396 
0397   class PlotsPerProcess {
0398   public:
0399     PlotsPerProcess(ProcessCallGraph::ProcessType const&);
0400     void book(dqm::reco::DQMStore::IBooker&,
0401               ProcessCallGraph const&,
0402               ProcessCallGraph::ProcessType const&,
0403               PlotRanges const& event_ranges,
0404               PlotRanges const& path_ranges,
0405               unsigned int lumisections,
0406               bool bypath,
0407               bool byls);
0408     void fill(ProcessCallGraph::ProcessType const&, ResourcesPerJob const&, ResourcesPerProcess const&, unsigned int ls);
0409 
0410   private:
0411     // resources spent in all the modules of the process
0412     PlotsPerElement event_;
0413     // resources spent in each path and endpath
0414     std::vector<PlotsPerPath> paths_;
0415     std::vector<PlotsPerPath> endpaths_;
0416   };
0417 
0418   class PlotsPerJob {
0419   public:
0420     PlotsPerJob(ProcessCallGraph const& job, std::vector<GroupOfModules> const& groups);
0421     void book(dqm::reco::DQMStore::IBooker&,
0422               ProcessCallGraph const&,
0423               std::vector<GroupOfModules> const&,
0424               PlotRanges const& event_ranges,
0425               PlotRanges const& path_ranges,
0426               PlotRanges const& module_ranges,
0427               unsigned int lumisections,
0428               bool bymodule,
0429               bool bypath,
0430               bool byls,
0431               bool transitions);
0432     void fill(ProcessCallGraph const&, ResourcesPerJob const&, unsigned int ls);
0433     void fill_run(AtomicResources const&);
0434     void fill_lumi(AtomicResources const&, unsigned int lumisection);
0435 
0436   private:
0437     // resources spent in all the modules of the job
0438     PlotsPerElement event_;
0439     PlotsPerElement event_ex_;
0440     PlotsPerElement overhead_;
0441     PlotsPerElement idle_;
0442     PlotsPerElement source_;
0443     // resources spent in the modules' lumi and run transitions
0444     PlotsPerElement lumi_;
0445     PlotsPerElement run_;
0446     // resources spent in the highlighted modules
0447     std::vector<PlotsPerElement> highlight_;
0448     // resources spent in each module
0449     std::vector<PlotsPerElement> modules_;
0450     // resources spent in process
0451     PlotsPerProcess process_;
0452   };
0453 
0454   // keep track of the dependencies among modules
0455   ProcessCallGraph callgraph_;
0456 
0457   // per-stream information
0458   std::vector<ResourcesPerJob> streams_;
0459 
0460   // concurrent histograms and profiles
0461   std::unique_ptr<PlotsPerJob> plots_;
0462 
0463   // per-lumi and per-run information
0464   std::vector<AtomicResources> lumi_transition_;  // resources spent in the modules' global and stream lumi transitions
0465   std::vector<AtomicResources> run_transition_;   // resources spent in the modules' global and stream run transitions
0466 
0467   // summary data
0468   ResourcesPerJob job_summary_;               // whole event time accounting per-job
0469   std::vector<ResourcesPerJob> run_summary_;  // whole event time accounting per-run
0470   std::mutex summary_mutex_;                  // synchronise access to the summary objects across different threads
0471 
0472   //
0473   struct ThreadGuard {
0474     struct specific_t {
0475       specific_t(AtomicResources& r) : resource_(r), live_(true) {}
0476       ~specific_t() = default;
0477 
0478       Measurement measurement_;
0479       AtomicResources& resource_;
0480       std::atomic<bool> live_;
0481     };
0482 
0483     ThreadGuard();
0484     ~ThreadGuard() = default;
0485 
0486     static void retire_thread(void* t);
0487     static std::shared_ptr<specific_t>* ptr(void* p);
0488 
0489     bool register_thread(FastTimerService::AtomicResources& r);
0490     Measurement& thread();
0491     void finalize();
0492 
0493     tbb::concurrent_vector<std::shared_ptr<specific_t>> thread_resources_;
0494     pthread_key_t key_;
0495   };
0496 
0497   //
0498   ThreadGuard guard_;
0499 
0500   // retrieve the current thread's per-thread quantities
0501   Measurement& thread();
0502 
0503   // job configuration
0504   unsigned int concurrent_lumis_;
0505   unsigned int concurrent_runs_;
0506   unsigned int concurrent_streams_;
0507   unsigned int concurrent_threads_;
0508 
0509   // logging configuration
0510   const bool print_event_summary_;  // print the time spent in each process, path and module after every event
0511   const bool print_run_summary_;    // print the time spent in each process, path and module for each run
0512   const bool print_job_summary_;    // print the time spent in each process, path and module for the whole job
0513 
0514   // JSON configuration
0515   //const bool write_json_per_event_;
0516   //const bool write_json_per_ls_;
0517   //const bool write_json_per_run_;
0518   const bool write_json_summary_;
0519   const std::string json_filename_;
0520 
0521   // dqm configuration
0522   bool enable_dqm_;  // non const, depends on the availability of the DQMStore
0523   const bool enable_dqm_bymodule_;
0524   const bool enable_dqm_bypath_;
0525   const bool enable_dqm_byls_;
0526   const bool enable_dqm_bynproc_;
0527   const bool enable_dqm_transitions_;
0528 
0529   const PlotRanges dqm_event_ranges_;
0530   const PlotRanges dqm_path_ranges_;
0531   const PlotRanges dqm_module_ranges_;
0532   const unsigned int dqm_lumisections_range_;
0533   std::string dqm_path_;
0534 
0535   std::vector<edm::ParameterSet> highlight_module_psets_;  // non-const, cleared in postBeginJob()
0536   std::vector<GroupOfModules> highlight_modules_;          // non-const, filled in postBeginJob()
0537 
0538   // log unsupported signals
0539   mutable tbb::concurrent_unordered_set<std::string> unsupported_signals_;  // keep track of unsupported signals received
0540 
0541   // print the resource usage summary for en event, a run, or the while job
0542   template <typename T>
0543   void printHeader(T& out, std::string const& label) const;
0544 
0545   template <typename T>
0546   void printEventHeader(T& out, std::string const& label) const;
0547 
0548   template <typename T>
0549   void printEventLine(T& out, Resources const& data, std::string const& label) const;
0550 
0551   template <typename T>
0552   void printEventLine(T& out, AtomicResources const& data, std::string const& label) const;
0553 
0554   template <typename T>
0555   void printEvent(T& out, ResourcesPerJob const&) const;
0556 
0557   template <typename T>
0558   void printSummaryHeader(T& out, std::string const& label, bool detailed) const;
0559 
0560   template <typename T>
0561   void printPathSummaryHeader(T& out, std::string const& label) const;
0562 
0563   template <typename T>
0564   void printSummaryLine(T& out, Resources const& data, uint64_t events, std::string const& label) const;
0565 
0566   template <typename T>
0567   void printSummaryLine(T& out, Resources const& data, uint64_t events, uint64_t active, std::string const& label) const;
0568 
0569   template <typename T>
0570   void printSummaryLine(T& out, AtomicResources const& data, uint64_t events, std::string const& label) const;
0571 
0572   template <typename T>
0573   void printSummaryLine(
0574       T& out, AtomicResources const& data, uint64_t events, uint64_t active, std::string const& label) const;
0575 
0576   template <typename T>
0577   void printPathSummaryLine(
0578       T& out, Resources const& data, Resources const& total, uint64_t events, std::string const& label) const;
0579 
0580   template <typename T>
0581   void printSummary(T& out, ResourcesPerJob const& data, std::string const& label) const;
0582 
0583   template <typename T>
0584   void printTransition(T& out, AtomicResources const& data, std::string const& label) const;
0585 
0586   template <typename T>
0587   json encodeToJSON(std::string const& type, std::string const& label, unsigned int events, T const& data) const;
0588 
0589   json encodeToJSON(edm::ModuleDescription const& module, ResourcesPerModule const& data) const;
0590 
0591   void writeSummaryJSON(ResourcesPerJob const& data, std::string const& filename) const;
0592 };
0593 
0594 #endif  // ! FastTimerService_h