CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_14/src/HLTrigger/Timer/src/FastTimerService.cc

Go to the documentation of this file.
00001 // FIXME
00002 // we are by-passing the ME's when filling the plots, so we might need to call the ME's update() by hand
00003 
00004 
00005 // system headers
00006 #ifdef __linux
00007 #include <time.h>
00008 #else
00009 typedef int clockid_t;
00010 #define CLOCK_REALTIME               0
00011 #define CLOCK_MONOTONIC              1
00012 #define CLOCK_PROCESS_CPUTIME_ID     2
00013 #define CLOCK_THREAD_CPUTIME_ID      3
00014 #endif
00015 
00016 // C++ headers
00017 #include <cmath>
00018 #include <limits>
00019 #include <iostream>
00020 #include <iomanip>
00021 #include <string>
00022 #include <sstream>
00023 #include <unordered_set>
00024 #include <unordered_map>
00025 
00026 // boost headers
00027 #include <boost/format.hpp>
00028 
00029 // CMSSW headers
00030 #include "FWCore/ServiceRegistry/interface/ActivityRegistry.h"
00031 #include "FWCore/ServiceRegistry/interface/Service.h"
00032 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00033 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
00034 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
00035 #include "FWCore/Framework/interface/Event.h"
00036 #include "FWCore/Framework/interface/LuminosityBlock.h"
00037 #include "FWCore/Framework/interface/TriggerNamesService.h"
00038 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00039 #include "DataFormats/Common/interface/HLTPathStatus.h"
00040 #include "DataFormats/Provenance/interface/EventID.h"
00041 #include "DataFormats/Provenance/interface/Timestamp.h"
00042 #include "DataFormats/Provenance/interface/ModuleDescription.h"
00043 #include "DataFormats/Scalers/interface/LumiScalers.h"
00044 #include "DQMServices/Core/interface/DQMStore.h"
00045 #include "DQMServices/Core/interface/MonitorElement.h"
00046 #include "HLTrigger/Timer/interface/FastTimerService.h"
00047 #include "HLTrigger/Timer/interface/CPUAffinity.h"
00048 
00049 
00050 // file-static methods to fill a vector of strings with "(dup.) (...)" entries
00051 static
00052 void fill_dups(std::vector<std::string> & dups, unsigned int size) {
00053   dups.reserve(size);
00054   for (unsigned int i = dups.size(); i < size; ++i)
00055     dups.push_back( (boost::format("(dup.) (%d)") % i).str() );
00056 }
00057 
00058 
00059 FastTimerService::FastTimerService(const edm::ParameterSet & config, edm::ActivityRegistry & registry) :
00060   // configuration
00061   m_timer_id(                    config.getUntrackedParameter<bool>(     "useRealTimeClock"         ) ? CLOCK_REALTIME : CLOCK_THREAD_CPUTIME_ID),
00062   m_is_cpu_bound(                false ),
00063   m_enable_timing_paths(         config.getUntrackedParameter<bool>(     "enableTimingPaths"        ) ),
00064   m_enable_timing_modules(       config.getUntrackedParameter<bool>(     "enableTimingModules"      ) ),
00065   m_enable_timing_exclusive(     config.getUntrackedParameter<bool>(     "enableTimingExclusive"    ) ),
00066   m_enable_timing_summary(       config.getUntrackedParameter<bool>(     "enableTimingSummary"      ) ),
00067   m_skip_first_path(             config.getUntrackedParameter<bool>(     "skipFirstPath"            ) ),
00068   // dqm configuration
00069   m_enable_dqm(                  config.getUntrackedParameter<bool>(     "enableDQM"                ) ),
00070   m_enable_dqm_bypath_active(    config.getUntrackedParameter<bool>(     "enableDQMbyPathActive"    ) ),
00071   m_enable_dqm_bypath_total(     config.getUntrackedParameter<bool>(     "enableDQMbyPathTotal"     ) ),
00072   m_enable_dqm_bypath_overhead(  config.getUntrackedParameter<bool>(     "enableDQMbyPathOverhead"  ) ),
00073   m_enable_dqm_bypath_details(   config.getUntrackedParameter<bool>(     "enableDQMbyPathDetails"   ) ),
00074   m_enable_dqm_bypath_counters(  config.getUntrackedParameter<bool>(     "enableDQMbyPathCounters"  ) ),
00075   m_enable_dqm_bypath_exclusive( config.getUntrackedParameter<bool>(     "enableDQMbyPathExclusive" ) ),
00076   m_enable_dqm_bymodule(         config.getUntrackedParameter<bool>(     "enableDQMbyModule"        ) ),
00077   m_enable_dqm_bymoduletype(     config.getUntrackedParameter<bool>(     "enableDQMbyModuleType"    ) ),
00078   m_enable_dqm_summary(          config.getUntrackedParameter<bool>(     "enableDQMSummary"         ) ),
00079   m_enable_dqm_byluminosity(     config.getUntrackedParameter<bool>(     "enableDQMbyLuminosity"    ) ),   
00080   m_enable_dqm_byls(             config.existsAs<bool>("enableDQMbyLumiSection", false) ? 
00081                                     config.getUntrackedParameter<bool>("enableDQMbyLumiSection") : 
00082                                     ( edm::LogWarning("Configuration") << "enableDQMbyLumi is deprecated, please use enableDQMbyLumiSection instead", config.getUntrackedParameter<bool>("enableDQMbyLumi") ) 
00083                                  ),
00084   m_enable_dqm_bynproc(          config.getUntrackedParameter<bool>(     "enableDQMbyProcesses"     ) ),
00085   m_nproc_enabled(               false ),
00086   m_dqm_eventtime_range(         config.getUntrackedParameter<double>(   "dqmTimeRange"             ) ),            // ms
00087   m_dqm_eventtime_resolution(    config.getUntrackedParameter<double>(   "dqmTimeResolution"        ) ),            // ms
00088   m_dqm_pathtime_range(          config.getUntrackedParameter<double>(   "dqmPathTimeRange"         ) ),            // ms
00089   m_dqm_pathtime_resolution(     config.getUntrackedParameter<double>(   "dqmPathTimeResolution"    ) ),            // ms
00090   m_dqm_moduletime_range(        config.getUntrackedParameter<double>(   "dqmModuleTimeRange"       ) ),            // ms
00091   m_dqm_moduletime_resolution(   config.getUntrackedParameter<double>(   "dqmModuleTimeResolution"  ) ),            // ms
00092   m_dqm_luminosity_range(        config.getUntrackedParameter<double>(   "dqmLuminosityRange"       ) / 1.e30),     // cm-2 s-1
00093   m_dqm_luminosity_resolution(   config.getUntrackedParameter<double>(   "dqmLuminosityResolution"  ) / 1.e30),     // cm-2 s-1
00094   m_dqm_ls_range(                config.getUntrackedParameter<uint32_t>( "dqmLumiSectionsRange"     ) ),            // lumisections
00095   m_dqm_path(                    config.getUntrackedParameter<std::string>("dqmPath" ) ),
00096   m_luminosity_label(            config.getUntrackedParameter<edm::InputTag>("luminosityProduct") ),                // SCAL unpacker
00097   m_supported_processes(         config.getUntrackedParameter<std::vector<unsigned int> >("supportedProcesses") ),  // 8, 24, 32
00098   // caching
00099   m_first_path(0),          // these are initialized at prePathBeginRun(),
00100   m_last_path(0),           // to make sure we cache the correct pointers
00101   m_first_endpath(0),
00102   m_last_endpath(0),
00103   m_is_first_module(false),
00104   // per-event accounting
00105   m_event(0.),
00106   m_source(0.),
00107   m_all_paths(0.),
00108   m_all_endpaths(0.),
00109   m_interpaths(0.),
00110   // per-job summary
00111   m_summary_events(0),
00112   m_summary_event(0.),
00113   m_summary_source(0.),
00114   m_summary_all_paths(0.),
00115   m_summary_all_endpaths(0.),
00116   m_summary_interpaths(0.),
00117   // DQM - these are initialized at preBeginRun(), to make sure the DQM service has been loaded
00118   m_dqms(0),
00119   // event summary plots
00120   m_dqm_event(0),
00121   m_dqm_source(0),
00122   m_dqm_all_paths(0),
00123   m_dqm_all_endpaths(0),
00124   m_dqm_interpaths(0),
00125   // event summary plots - summed over nodes with the same number of processes
00126   m_dqm_nproc_event(0),
00127   m_dqm_nproc_source(0),
00128   m_dqm_nproc_all_paths(0),
00129   m_dqm_nproc_all_endpaths(0),
00130   m_dqm_nproc_interpaths(0),
00131   // plots by path
00132   m_dqm_paths_active_time(0),
00133   m_dqm_paths_total_time(0),
00134   m_dqm_paths_exclusive_time(0),
00135   m_dqm_paths_interpaths(0),
00136   // plots per lumisection
00137   m_dqm_byls_event(0),
00138   m_dqm_byls_source(0),
00139   m_dqm_byls_all_paths(0),
00140   m_dqm_byls_all_endpaths(0),
00141   m_dqm_byls_interpaths(0),
00142   // plots per lumisection - summed over nodes with the same number of processes
00143   m_dqm_nproc_byls_event(0),
00144   m_dqm_nproc_byls_source(0),
00145   m_dqm_nproc_byls_all_paths(0),
00146   m_dqm_nproc_byls_all_endpaths(0),
00147   m_dqm_nproc_byls_interpaths(0),
00148   // plots vs. instantaneous luminosity
00149   m_dqm_byluminosity_event(0),
00150   m_dqm_byluminosity_source(0),
00151   m_dqm_byluminosity_all_paths(0),
00152   m_dqm_byluminosity_all_endpaths(0),
00153   m_dqm_byluminosity_interpaths(0),
00154   // plots vs. instantaneous luminosity - summed over nodes with the same number of processes
00155   m_dqm_nproc_byluminosity_event(0),
00156   m_dqm_nproc_byluminosity_source(0),
00157   m_dqm_nproc_byluminosity_all_paths(0),
00158   m_dqm_nproc_byluminosity_all_endpaths(0),
00159   m_dqm_nproc_byluminosity_interpaths(0),
00160   // per-path and per-module accounting
00161   m_current_path(0),
00162   m_paths(),
00163   m_modules(),
00164   m_moduletypes(),
00165   m_fast_modules(),
00166   m_fast_moduletypes()
00167 {
00168   // enable timers if required by DQM plots
00169   m_enable_timing_paths     = m_enable_timing_paths         or 
00170                               m_enable_dqm_bypath_active    or 
00171                               m_enable_dqm_bypath_total     or 
00172                               m_enable_dqm_bypath_overhead  or 
00173                               m_enable_dqm_bypath_details   or 
00174                               m_enable_dqm_bypath_counters  or 
00175                               m_enable_dqm_bypath_exclusive;
00176 
00177   m_enable_timing_modules   = m_enable_timing_modules       or 
00178                               m_enable_dqm_bymodule         or 
00179                               m_enable_dqm_bymoduletype     or 
00180                               m_enable_dqm_bypath_total     or 
00181                               m_enable_dqm_bypath_overhead  or 
00182                               m_enable_dqm_bypath_details   or 
00183                               m_enable_dqm_bypath_counters  or 
00184                               m_enable_dqm_bypath_exclusive;
00185 
00186   m_enable_timing_exclusive = m_enable_timing_exclusive     or 
00187                               m_enable_dqm_bypath_exclusive;
00188 
00189   registry.watchPreModuleBeginJob( this, & FastTimerService::preModuleBeginJob );
00190   registry.watchPreBeginRun(       this, & FastTimerService::preBeginRun );
00191   registry.watchPostEndJob(        this, & FastTimerService::postEndJob );
00192   registry.watchPrePathBeginRun(   this, & FastTimerService::prePathBeginRun) ;
00193   registry.watchPreProcessEvent(   this, & FastTimerService::preProcessEvent );
00194   registry.watchPostProcessEvent(  this, & FastTimerService::postProcessEvent );
00195   registry.watchPreSource(         this, & FastTimerService::preSource );
00196   registry.watchPostSource(        this, & FastTimerService::postSource );
00197   // watch per-path events
00198   registry.watchPreProcessPath(    this, & FastTimerService::preProcessPath );
00199   registry.watchPostProcessPath(   this, & FastTimerService::postProcessPath );
00200   // watch per-module events if enabled
00201   if (m_enable_timing_modules) {
00202     registry.watchPreModule(         this, & FastTimerService::preModule );
00203     registry.watchPostModule(        this, & FastTimerService::postModule );
00204   }
00205 
00206 #if defined(__APPLE__) || defined (__MACH__)
00207   host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &m_clock_port);
00208 #endif // defined(__APPLE__) || defined(__MACH__)
00209 }
00210 
00211 FastTimerService::~FastTimerService()
00212 {
00213 #if defined(__APPLE__) || defined (__MACH__)
00214   mach_port_deallocate(mach_task_self(), m_clock_port);
00215 #endif // defined(__APPLE__) || defined(__MACH__)
00216 }
00217 
00218 void FastTimerService::preBeginRun( edm::RunID const &, edm::Timestamp const & )
00219 {
00220   //edm::LogImportant("FastTimerService") << __func__ << "()";
00221 
00222   // check if the process is bound to a single CPU.
00223   // otherwise, the results of the CLOCK_THREAD_CPUTIME_ID timer might be inaccurate
00224 #ifdef __linux
00225   // cpu affinity is currently only supported on LINUX
00226   m_is_cpu_bound = CPUAffinity::isCpuBound();
00227   if ((m_timer_id != CLOCK_REALTIME) and not m_is_cpu_bound) {
00228     clockid_t clock;
00229     if (clock_getcpuclockid(0, & clock) == ENOENT)
00230       // the process is NOT bound to a single CPU, and the system does not support a consistent time source across multiple CPUs
00231       edm::LogError("FastTimerService") << "this process is NOT bound to a single CPU, the results of the FastTimerService may be undefined";
00232   }
00233 #endif
00234 
00235   edm::service::TriggerNamesService & tns = * edm::Service<edm::service::TriggerNamesService>();
00236   uint32_t size_p = tns.getTrigPaths().size();
00237   uint32_t size_e = tns.getEndPaths().size();
00238   uint32_t size = size_p + size_e;
00239   for (uint32_t i = 0; i < size_p; ++i) {
00240     std::string const & label = tns.getTrigPath(i);
00241     m_paths[label].index = i;
00242   }
00243   for (uint32_t i = 0; i < size_e; ++i) {
00244     std::string const & label = tns.getEndPath(i);
00245     m_paths[label].index = size_p + i;
00246   }
00247 
00248   // associate to each path all the modules it contains
00249   for (uint32_t i = 0; i < tns.getTrigPaths().size(); ++i)
00250     fillPathMap( tns.getTrigPath(i), tns.getTrigPathModules(i) );
00251   for (uint32_t i = 0; i < tns.getEndPaths().size(); ++i)
00252     fillPathMap( tns.getEndPath(i), tns.getEndPathModules(i) );
00253 
00254   if (m_enable_dqm)
00255     // load the DQM store
00256     m_dqms = edm::Service<DQMStore>().operator->();
00257 
00258   if (m_dqms) {
00259     // book MonitorElement's
00260     int eventbins  = (int) std::ceil(m_dqm_eventtime_range  / m_dqm_eventtime_resolution);
00261     int pathbins   = (int) std::ceil(m_dqm_pathtime_range   / m_dqm_pathtime_resolution);
00262     int modulebins = (int) std::ceil(m_dqm_moduletime_range / m_dqm_moduletime_resolution);
00263     int lumibins   = (int) std::ceil(m_dqm_luminosity_range / m_dqm_luminosity_resolution);
00264 
00265     // event summary plots
00266     if (m_enable_dqm_summary) {
00267       m_dqms->setCurrentFolder(m_dqm_path);
00268       m_dqm_event         = m_dqms->book1D("event",        "Event processing time",    eventbins, 0., m_dqm_eventtime_range)->getTH1F();
00269       m_dqm_event         ->StatOverflows(true);
00270       m_dqm_event         ->SetXTitle("processing time [ms]");
00271       m_dqm_source        = m_dqms->book1D("source",       "Source processing time",   pathbins,  0., m_dqm_pathtime_range)->getTH1F();
00272       m_dqm_source        ->StatOverflows(true);
00273       m_dqm_source        ->SetXTitle("processing time [ms]");
00274       m_dqm_all_paths     = m_dqms->book1D("all_paths",    "Paths processing time",    eventbins, 0., m_dqm_eventtime_range)->getTH1F();
00275       m_dqm_all_paths     ->StatOverflows(true);
00276       m_dqm_all_paths     ->SetXTitle("processing time [ms]");
00277       m_dqm_all_endpaths  = m_dqms->book1D("all_endpaths", "EndPaths processing time", pathbins,  0., m_dqm_pathtime_range)->getTH1F();
00278       m_dqm_all_endpaths  ->StatOverflows(true);
00279       m_dqm_all_endpaths  ->SetXTitle("processing time [ms]");
00280       m_dqm_interpaths    = m_dqms->book1D("interpaths",   "Time spent between paths", pathbins,  0., m_dqm_eventtime_range)->getTH1F();
00281       m_dqm_interpaths    ->StatOverflows(true);
00282       m_dqm_interpaths    ->SetXTitle("processing time [ms]");
00283     }
00284 
00285     // event summary plots - summed over nodes with the same number of processes
00286     if (m_enable_dqm_summary and m_enable_dqm_bynproc) {
00287       TH1F * plot;
00288       for (int n : m_supported_processes) {
00289         m_dqms->setCurrentFolder( (boost::format("%s/Running %d processes") % m_dqm_path % n).str() );
00290         plot = m_dqms->book1D("event",        "Event processing time",    eventbins, 0., m_dqm_eventtime_range)->getTH1F();
00291         plot->StatOverflows(true);
00292         plot->SetXTitle("processing time [ms]");
00293         plot = m_dqms->book1D("source",       "Source processing time",   pathbins,  0., m_dqm_pathtime_range)->getTH1F();
00294         plot->StatOverflows(true);
00295         plot->SetXTitle("processing time [ms]");
00296         plot = m_dqms->book1D("all_paths",    "Paths processing time",    eventbins, 0., m_dqm_eventtime_range)->getTH1F();
00297         plot->StatOverflows(true);
00298         plot->SetXTitle("processing time [ms]");
00299         plot = m_dqms->book1D("all_endpaths", "EndPaths processing time", pathbins,  0., m_dqm_pathtime_range)->getTH1F();
00300         plot->StatOverflows(true);
00301         plot->SetXTitle("processing time [ms]");
00302         plot = m_dqms->book1D("interpaths",   "Time spent between paths", pathbins,  0., m_dqm_eventtime_range)->getTH1F();
00303         plot->StatOverflows(true);
00304         plot->SetXTitle("processing time [ms]");
00305       }
00306     }
00307 
00308     // plots by path
00309     m_dqms->setCurrentFolder(m_dqm_path);
00310     m_dqm_paths_active_time     = m_dqms->bookProfile("paths_active_time",    "Additional time spent in each path", size, -0.5, size-0.5, pathbins, 0., std::numeric_limits<double>::infinity(), " ")->getTProfile();
00311     m_dqm_paths_active_time     ->StatOverflows(true);
00312     m_dqm_paths_active_time     ->SetYTitle("processing time [ms]");
00313     m_dqm_paths_total_time      = m_dqms->bookProfile("paths_total_time",     "Total time spent in each path",      size, -0.5, size-0.5, pathbins, 0., std::numeric_limits<double>::infinity(), " ")->getTProfile();
00314     m_dqm_paths_total_time      ->StatOverflows(true);
00315     m_dqm_paths_total_time      ->SetYTitle("processing time [ms]");
00316     m_dqm_paths_exclusive_time  = m_dqms->bookProfile("paths_exclusive_time", "Exclusive time spent in each path",  size, -0.5, size-0.5, pathbins, 0., std::numeric_limits<double>::infinity(), " ")->getTProfile();
00317     m_dqm_paths_exclusive_time  ->StatOverflows(true);
00318     m_dqm_paths_exclusive_time  ->SetYTitle("processing time [ms]");
00319     m_dqm_paths_interpaths      = m_dqms->bookProfile("paths_interpaths",     "Time spent between each path",       size, -0.5, size-0.5, pathbins, 0., std::numeric_limits<double>::infinity(), " ")->getTProfile();
00320     m_dqm_paths_interpaths      ->StatOverflows(true);
00321     m_dqm_paths_interpaths      ->SetYTitle("processing time [ms]");
00322 
00323     for (uint32_t i = 0; i < size_p; ++i) {
00324       std::string const & label = tns.getTrigPath(i);
00325       m_dqm_paths_active_time    ->GetXaxis()->SetBinLabel(i + 1, label.c_str());
00326       m_dqm_paths_total_time     ->GetXaxis()->SetBinLabel(i + 1, label.c_str());
00327       m_dqm_paths_exclusive_time ->GetXaxis()->SetBinLabel(i + 1, label.c_str());
00328       m_dqm_paths_interpaths     ->GetXaxis()->SetBinLabel(i + 1, label.c_str());
00329     }
00330     for (uint32_t i = 0; i < size_e; ++i) {
00331       std::string const & label = tns.getEndPath(i);
00332       m_dqm_paths_active_time    ->GetXaxis()->SetBinLabel(i + size_p + 1, label.c_str());
00333       m_dqm_paths_total_time     ->GetXaxis()->SetBinLabel(i + size_p + 1, label.c_str());
00334       m_dqm_paths_exclusive_time ->GetXaxis()->SetBinLabel(i + size_p + 1, label.c_str());
00335       m_dqm_paths_interpaths     ->GetXaxis()->SetBinLabel(i + size_p + 1, label.c_str());
00336     }
00337 
00338     // per-lumisection plots
00339     if (m_enable_dqm_byls) {
00340       m_dqms->setCurrentFolder(m_dqm_path);
00341       m_dqm_byls_event        = m_dqms->bookProfile("event_byls",        "Event processing time, by LumiSection",    m_dqm_ls_range, 0.5, m_dqm_ls_range+0.5, eventbins, 0., std::numeric_limits<double>::infinity(), " ")->getTProfile();
00342       m_dqm_byls_event        ->StatOverflows(true);
00343       m_dqm_byls_event        ->SetXTitle("lumisection");
00344       m_dqm_byls_event        ->SetYTitle("processing time [ms]");
00345       m_dqm_byls_source       = m_dqms->bookProfile("source_byls",       "Source processing time, by LumiSection",   m_dqm_ls_range, 0.5, m_dqm_ls_range+0.5, pathbins,  0., std::numeric_limits<double>::infinity(), " ")->getTProfile();
00346       m_dqm_byls_source       ->StatOverflows(true);
00347       m_dqm_byls_source       ->SetXTitle("lumisection");
00348       m_dqm_byls_source       ->SetYTitle("processing time [ms]");
00349       m_dqm_byls_all_paths    = m_dqms->bookProfile("all_paths_byls",    "Paths processing time, by LumiSection",    m_dqm_ls_range, 0.5, m_dqm_ls_range+0.5, eventbins, 0., std::numeric_limits<double>::infinity(), " ")->getTProfile();
00350       m_dqm_byls_all_paths    ->StatOverflows(true);
00351       m_dqm_byls_all_paths    ->SetXTitle("lumisection");
00352       m_dqm_byls_all_paths    ->SetYTitle("processing time [ms]");
00353       m_dqm_byls_all_endpaths = m_dqms->bookProfile("all_endpaths_byls", "EndPaths processing time, by LumiSection", m_dqm_ls_range, 0.5, m_dqm_ls_range+0.5, pathbins,  0., std::numeric_limits<double>::infinity(), " ")->getTProfile();
00354       m_dqm_byls_all_endpaths ->StatOverflows(true);
00355       m_dqm_byls_all_endpaths ->SetXTitle("lumisection");
00356       m_dqm_byls_all_endpaths ->SetYTitle("processing time [ms]");
00357       m_dqm_byls_interpaths   = m_dqms->bookProfile("interpaths_byls",   "Time spent between paths, by LumiSection", m_dqm_ls_range, 0.5, m_dqm_ls_range+0.5, pathbins,  0., std::numeric_limits<double>::infinity(), " ")->getTProfile();
00358       m_dqm_byls_interpaths   ->StatOverflows(true);
00359       m_dqm_byls_interpaths   ->SetXTitle("lumisection");
00360       m_dqm_byls_interpaths   ->SetYTitle("processing time [ms]");
00361     }
00362 
00363     // per-lumisection plots
00364     if (m_enable_dqm_byls and m_enable_dqm_bynproc) {
00365       TProfile * plot;
00366       for (int n : m_supported_processes) {
00367         m_dqms->setCurrentFolder( (boost::format("%s/Running %d processes") % m_dqm_path % n).str() );
00368         plot = m_dqms->bookProfile("event_byls",        "Event processing time, by LumiSection",    m_dqm_ls_range, 0.5, m_dqm_ls_range+0.5, eventbins, 0., std::numeric_limits<double>::infinity(), " ")->getTProfile();
00369         plot->StatOverflows(true);
00370         plot->SetXTitle("lumisection");
00371         plot->SetYTitle("processing time [ms]");
00372         plot = m_dqms->bookProfile("source_byls",       "Source processing time, by LumiSection",   m_dqm_ls_range, 0.5, m_dqm_ls_range+0.5, pathbins,  0., std::numeric_limits<double>::infinity(), " ")->getTProfile();
00373         plot->StatOverflows(true);
00374         plot->SetXTitle("lumisection");
00375         plot->SetYTitle("processing time [ms]");
00376         plot = m_dqms->bookProfile("all_paths_byls",    "Paths processing time, by LumiSection",    m_dqm_ls_range, 0.5, m_dqm_ls_range+0.5, eventbins, 0., std::numeric_limits<double>::infinity(), " ")->getTProfile();
00377         plot->StatOverflows(true);
00378         plot->SetXTitle("lumisection");
00379         plot->SetYTitle("processing time [ms]");
00380         plot = m_dqms->bookProfile("all_endpaths_byls", "EndPaths processing time, by LumiSection", m_dqm_ls_range, 0.5, m_dqm_ls_range+0.5, pathbins,  0., std::numeric_limits<double>::infinity(), " ")->getTProfile();
00381         plot->StatOverflows(true);
00382         plot->SetXTitle("lumisection");
00383         plot->SetYTitle("processing time [ms]");
00384         plot = m_dqms->bookProfile("interpaths_byls",   "Time spent between paths, by LumiSection", m_dqm_ls_range, 0.5, m_dqm_ls_range+0.5, pathbins,  0., std::numeric_limits<double>::infinity(), " ")->getTProfile();
00385         plot->StatOverflows(true);
00386         plot->SetXTitle("lumisection");
00387         plot->SetYTitle("processing time [ms]");
00388       }
00389     }
00390 
00391     // plots vs. instantaneous luminosity
00392     if (m_enable_dqm_byluminosity) {
00393       m_dqms->setCurrentFolder(m_dqm_path);
00394       m_dqm_byluminosity_event        = m_dqms->bookProfile("event_byluminosity",        "Event processing time vs. instantaneous luminosity",    lumibins, 0., m_dqm_luminosity_range, eventbins, 0., std::numeric_limits<double>::infinity(), " ")->getTProfile();
00395       m_dqm_byluminosity_event        ->StatOverflows(true);
00396       m_dqm_byluminosity_event        ->SetXTitle("instantaneous luminosity [10^{30} cm^{-2}s^{-1}]");
00397       m_dqm_byluminosity_event        ->SetYTitle("processing time [ms]");
00398       m_dqm_byluminosity_source       = m_dqms->bookProfile("source_byluminosity",       "Source processing time vs. instantaneous luminosity",   lumibins, 0., m_dqm_luminosity_range, pathbins,  0., std::numeric_limits<double>::infinity(), " ")->getTProfile();
00399       m_dqm_byluminosity_source       ->StatOverflows(true);
00400       m_dqm_byluminosity_source       ->SetXTitle("instantaneous luminosity [10^{30} cm^{-2}s^{-1}]");
00401       m_dqm_byluminosity_source       ->SetYTitle("processing time [ms]");
00402       m_dqm_byluminosity_all_paths    = m_dqms->bookProfile("all_paths_byluminosity",    "Paths processing time vs. instantaneous luminosity",    lumibins, 0., m_dqm_luminosity_range, eventbins, 0., std::numeric_limits<double>::infinity(), " ")->getTProfile();
00403       m_dqm_byluminosity_all_paths    ->StatOverflows(true);
00404       m_dqm_byluminosity_all_paths    ->SetXTitle("instantaneous luminosity [10^{30} cm^{-2}s^{-1}]");
00405       m_dqm_byluminosity_all_paths    ->SetYTitle("processing time [ms]");
00406       m_dqm_byluminosity_all_endpaths = m_dqms->bookProfile("all_endpaths_byluminosity", "EndPaths processing time vs. instantaneous luminosity", lumibins, 0., m_dqm_luminosity_range, pathbins,  0., std::numeric_limits<double>::infinity(), " ")->getTProfile();
00407       m_dqm_byluminosity_all_endpaths ->StatOverflows(true);
00408       m_dqm_byluminosity_all_endpaths ->SetXTitle("instantaneous luminosity [10^{30} cm^{-2}s^{-1}]");
00409       m_dqm_byluminosity_all_endpaths ->SetYTitle("processing time [ms]");
00410       m_dqm_byluminosity_interpaths   = m_dqms->bookProfile("interpaths_byluminosity",   "Time spent between paths vs. instantaneous luminosity", lumibins, 0., m_dqm_luminosity_range, pathbins,  0., std::numeric_limits<double>::infinity(), " ")->getTProfile();
00411       m_dqm_byluminosity_interpaths   ->StatOverflows(true);
00412       m_dqm_byluminosity_interpaths   ->SetXTitle("instantaneous luminosity [10^{30} cm^{-2}s^{-1}]");
00413       m_dqm_byluminosity_interpaths   ->SetYTitle("processing time [ms]");
00414     }
00415 
00416     // plots vs. instantaneous luminosity
00417     if (m_enable_dqm_byluminosity and m_enable_dqm_bynproc) {
00418       TProfile * plot;
00419       for (int n : m_supported_processes) {
00420         m_dqms->setCurrentFolder( (boost::format("%s/Running %d processes") % m_dqm_path % n).str() );
00421         plot = m_dqms->bookProfile("event_byluminosity",        "Event processing time vs. instantaneous luminosity",    lumibins, 0., m_dqm_luminosity_range, eventbins, 0., std::numeric_limits<double>::infinity(), " ")->getTProfile();
00422         plot->StatOverflows(true);
00423         plot->SetYTitle("processing time [ms]");
00424         plot->SetXTitle("instantaneous luminosity [10^{30} cm^{-2}s^{-1}]");
00425         plot = m_dqms->bookProfile("source_byluminosity",       "Source processing time vs. instantaneous luminosity",   lumibins, 0., m_dqm_luminosity_range, pathbins,  0., std::numeric_limits<double>::infinity(), " ")->getTProfile();
00426         plot->StatOverflows(true);
00427         plot->SetYTitle("processing time [ms]");
00428         plot->SetXTitle("instantaneous luminosity [10^{30} cm^{-2}s^{-1}]");
00429         plot = m_dqms->bookProfile("all_paths_byluminosity",    "Paths processing time vs. instantaneous luminosity",    lumibins, 0., m_dqm_luminosity_range, eventbins, 0., std::numeric_limits<double>::infinity(), " ")->getTProfile();
00430         plot->StatOverflows(true);
00431         plot->SetYTitle("processing time [ms]");
00432         plot->SetXTitle("instantaneous luminosity [10^{30} cm^{-2}s^{-1}]");
00433         plot = m_dqms->bookProfile("all_endpaths_byluminosity", "EndPaths processing time vs. instantaneous luminosity", lumibins, 0., m_dqm_luminosity_range, pathbins,  0., std::numeric_limits<double>::infinity(), " ")->getTProfile();
00434         plot->StatOverflows(true);
00435         plot->SetYTitle("processing time [ms]");
00436         plot->SetXTitle("instantaneous luminosity [10^{30} cm^{-2}s^{-1}]");
00437         plot = m_dqms->bookProfile("interpaths_byluminosity",   "Time spent between paths vs. instantaneous luminosity", lumibins, 0., m_dqm_luminosity_range, pathbins,  0., std::numeric_limits<double>::infinity(), " ")->getTProfile();
00438         plot->StatOverflows(true);
00439         plot->SetYTitle("processing time [ms]");
00440         plot->SetXTitle("instantaneous luminosity [10^{30} cm^{-2}s^{-1}]");
00441       }
00442     }
00443 
00444     // per-path and per-module accounting
00445     if (m_enable_timing_paths) {
00446       m_dqms->setCurrentFolder((m_dqm_path + "/Paths"));
00447       for (auto & keyval: m_paths) {
00448         std::string const & pathname = keyval.first;
00449         PathInfo          & pathinfo = keyval.second;
00450 
00451         if (m_enable_dqm_bypath_active) {
00452           pathinfo.dqm_active       = m_dqms->book1D(pathname + "_active",       pathname + " active time",            pathbins, 0., m_dqm_pathtime_range)->getTH1F();
00453           pathinfo.dqm_active       ->StatOverflows(true);
00454           pathinfo.dqm_active       ->SetXTitle("processing time [ms]");
00455         }
00456 
00457         if (m_enable_dqm_bypath_total) {
00458           pathinfo.dqm_total        = m_dqms->book1D(pathname + "_total",        pathname + " total time",             pathbins, 0., m_dqm_pathtime_range)->getTH1F();
00459           pathinfo.dqm_total        ->StatOverflows(true);
00460           pathinfo.dqm_total        ->SetXTitle("processing time [ms]");
00461         }
00462 
00463         if (m_enable_dqm_bypath_overhead) {
00464           pathinfo.dqm_premodules   = m_dqms->book1D(pathname + "_premodules",   pathname + " pre-modules overhead",   modulebins, 0., m_dqm_moduletime_range)->getTH1F();
00465           pathinfo.dqm_premodules   ->StatOverflows(true);
00466           pathinfo.dqm_premodules   ->SetXTitle("processing time [ms]");
00467           pathinfo.dqm_intermodules = m_dqms->book1D(pathname + "_intermodules", pathname + " inter-modules overhead", modulebins, 0., m_dqm_moduletime_range)->getTH1F();
00468           pathinfo.dqm_intermodules ->StatOverflows(true);
00469           pathinfo.dqm_intermodules ->SetXTitle("processing time [ms]");
00470           pathinfo.dqm_postmodules  = m_dqms->book1D(pathname + "_postmodules",  pathname + " post-modules overhead",  modulebins, 0., m_dqm_moduletime_range)->getTH1F();
00471           pathinfo.dqm_postmodules  ->StatOverflows(true);
00472           pathinfo.dqm_postmodules  ->SetXTitle("processing time [ms]");
00473           pathinfo.dqm_overhead     = m_dqms->book1D(pathname + "_overhead",     pathname + " overhead time",          modulebins, 0., m_dqm_moduletime_range)->getTH1F();
00474           pathinfo.dqm_overhead     ->StatOverflows(true);
00475           pathinfo.dqm_overhead     ->SetXTitle("processing time [ms]");
00476         }
00477 
00478         if (m_enable_dqm_bypath_details or m_enable_dqm_bypath_counters) {
00479           // book histograms for modules-in-paths statistics
00480 
00481           // find histograms X-axis labels
00482           uint32_t id;
00483           std::vector<std::string> const & modules = ((id = tns.findTrigPath(pathname)) != tns.getTrigPaths().size()) ? tns.getTrigPathModules(id) :
00484                                                      ((id = tns.findEndPath(pathname))  != tns.getEndPaths().size())  ? tns.getEndPathModules(id)  :
00485                                                      std::vector<std::string>();
00486 
00487           static std::vector<std::string> dup;
00488           if (modules.size() > dup.size())
00489             fill_dups(dup, modules.size());
00490 
00491           std::vector<const char *> labels(modules.size(), nullptr);
00492           for (uint32_t i = 0; i < modules.size(); ++i)
00493             labels[i] = (pathinfo.modules[i]) ? modules[i].c_str() : dup[i].c_str();
00494           
00495           // book counter histograms
00496           if (m_enable_dqm_bypath_counters) {
00497             pathinfo.dqm_module_counter = m_dqms->book1D(pathname + "_module_counter", pathname + " module counter", modules.size(), -0.5, modules.size() - 0.5)->getTH1F();
00498             // find module labels
00499             for (uint32_t i = 0; i < modules.size(); ++i) {
00500               pathinfo.dqm_module_counter->GetXaxis()->SetBinLabel( i+1, labels[i] );
00501             }
00502           }
00503           // book detailed timing histograms
00504           if (m_enable_dqm_bypath_details) {
00505             pathinfo.dqm_module_active  = m_dqms->book1D(pathname + "_module_active",  pathname + " module active",  modules.size(), -0.5, modules.size() - 0.5)->getTH1F();
00506             pathinfo.dqm_module_active  ->SetYTitle("cumulative processing time [ms]");
00507             pathinfo.dqm_module_total   = m_dqms->book1D(pathname + "_module_total",   pathname + " module total",   modules.size(), -0.5, modules.size() - 0.5)->getTH1F();
00508             pathinfo.dqm_module_total   ->SetYTitle("cumulative processing time [ms]");
00509             // find module labels
00510             for (uint32_t i = 0; i < modules.size(); ++i) {
00511               pathinfo.dqm_module_active ->GetXaxis()->SetBinLabel( i+1, labels[i] );
00512               pathinfo.dqm_module_total  ->GetXaxis()->SetBinLabel( i+1, labels[i] );
00513             }
00514           }
00515         }
00516 
00517         // book exclusive path time histograms
00518         if (m_enable_dqm_bypath_exclusive) {
00519           pathinfo.dqm_exclusive = m_dqms->book1D(pathname + "_exclusive", pathname + " exclusive time", pathbins, 0., m_dqm_pathtime_range)->getTH1F();
00520           pathinfo.dqm_exclusive ->StatOverflows(true);
00521           pathinfo.dqm_exclusive ->SetXTitle("processing time [ms]");
00522         }
00523 
00524       }
00525     }
00526    
00527     if (m_enable_dqm_bymodule) {
00528       m_dqms->setCurrentFolder((m_dqm_path + "/Modules"));
00529       for (auto & keyval: m_modules) {
00530         std::string const & label  = keyval.first;
00531         ModuleInfo        & module = keyval.second;
00532         module.dqm_active = m_dqms->book1D(label, label, modulebins, 0., m_dqm_moduletime_range)->getTH1F();
00533         module.dqm_active->StatOverflows(true);
00534         module.dqm_active->SetXTitle("processing time [ms]");
00535       }
00536     }
00537 
00538     if (m_enable_dqm_bymoduletype) {
00539       m_dqms->setCurrentFolder((m_dqm_path + "/ModuleTypes"));
00540       for (auto & keyval: m_moduletypes) {
00541         std::string const & label  = keyval.first;
00542         ModuleInfo        & module = keyval.second;
00543         module.dqm_active = m_dqms->book1D(label, label, modulebins, 0., m_dqm_moduletime_range)->getTH1F();
00544         module.dqm_active->StatOverflows(true);
00545         module.dqm_active->SetXTitle("processing time [ms]");
00546       }
00547     }
00548 
00549   }
00550 }
00551 
00552 void FastTimerService::setNumberOfProcesses(unsigned int procs) {
00553   // the service is not configured to support plots by number of processes
00554   if (not m_enable_dqm or not m_enable_dqm_bynproc)
00555     return;
00556 
00557   // the DQM store has not been configured yet
00558   if (not m_dqms)
00559     return;
00560 
00561   // check if the service is configured to support this number of processes
00562   if (std::find(m_supported_processes.begin(), m_supported_processes.end(), procs) == m_supported_processes.end()) {
00563     m_nproc_enabled = false;
00564     // event summary plots - summed over nodes with the same number of processes
00565     m_dqm_nproc_event                     = 0;
00566     m_dqm_nproc_source                    = 0;
00567     m_dqm_nproc_all_paths                 = 0;
00568     m_dqm_nproc_all_endpaths              = 0;
00569     m_dqm_nproc_interpaths                = 0;
00570     // plots per lumisection - summed over nodes with the same number of processes
00571     m_dqm_nproc_byls_event                = 0;
00572     m_dqm_nproc_byls_source               = 0;
00573     m_dqm_nproc_byls_all_paths            = 0;
00574     m_dqm_nproc_byls_all_endpaths         = 0;
00575     m_dqm_nproc_byls_interpaths           = 0;
00576     // plots vs. instantaneous luminosity - summed over nodes with the same number of processes
00577     m_dqm_nproc_byluminosity_event        = 0;
00578     m_dqm_nproc_byluminosity_source       = 0;
00579     m_dqm_nproc_byluminosity_all_paths    = 0;
00580     m_dqm_nproc_byluminosity_all_endpaths = 0;
00581     m_dqm_nproc_byluminosity_interpaths   = 0;
00582   } else {
00583     m_nproc_enabled = true;
00584     // event summary plots - summed over nodes with the same number of processes
00585     m_dqm_nproc_event                     = m_dqms->get( (boost::format("%s/Running %d processes/%s") % m_dqm_path % procs % "event"                    ).str() )->getTH1F();
00586     m_dqm_nproc_source                    = m_dqms->get( (boost::format("%s/Running %d processes/%s") % m_dqm_path % procs % "source"                   ).str() )->getTH1F();
00587     m_dqm_nproc_all_paths                 = m_dqms->get( (boost::format("%s/Running %d processes/%s") % m_dqm_path % procs % "all_paths"                ).str() )->getTH1F();
00588     m_dqm_nproc_all_endpaths              = m_dqms->get( (boost::format("%s/Running %d processes/%s") % m_dqm_path % procs % "all_endpaths"             ).str() )->getTH1F();
00589     m_dqm_nproc_interpaths                = m_dqms->get( (boost::format("%s/Running %d processes/%s") % m_dqm_path % procs % "interpaths"               ).str() )->getTH1F();
00590     // plots per lumisection - summed over nodes with the same number of processes
00591     m_dqm_nproc_byls_event                = m_dqms->get( (boost::format("%s/Running %d processes/%s") % m_dqm_path % procs % "event_byls"               ).str() )->getTProfile();
00592     m_dqm_nproc_byls_source               = m_dqms->get( (boost::format("%s/Running %d processes/%s") % m_dqm_path % procs % "source_byls"              ).str() )->getTProfile();
00593     m_dqm_nproc_byls_all_paths            = m_dqms->get( (boost::format("%s/Running %d processes/%s") % m_dqm_path % procs % "all_paths_byls"           ).str() )->getTProfile();
00594     m_dqm_nproc_byls_all_endpaths         = m_dqms->get( (boost::format("%s/Running %d processes/%s") % m_dqm_path % procs % "all_endpaths_byls"        ).str() )->getTProfile();
00595     m_dqm_nproc_byls_interpaths           = m_dqms->get( (boost::format("%s/Running %d processes/%s") % m_dqm_path % procs % "interpaths_byls"          ).str() )->getTProfile();
00596     // plots vs. instantaneous luminosity - summed over nodes with the same number of processes
00597     m_dqm_nproc_byluminosity_event        = m_dqms->get( (boost::format("%s/Running %d processes/%s") % m_dqm_path % procs % "event_byluminosity"       ).str() )->getTProfile();
00598     m_dqm_nproc_byluminosity_source       = m_dqms->get( (boost::format("%s/Running %d processes/%s") % m_dqm_path % procs % "source_byluminosity"      ).str() )->getTProfile();
00599     m_dqm_nproc_byluminosity_all_paths    = m_dqms->get( (boost::format("%s/Running %d processes/%s") % m_dqm_path % procs % "all_paths_byluminosity"   ).str() )->getTProfile();
00600     m_dqm_nproc_byluminosity_all_endpaths = m_dqms->get( (boost::format("%s/Running %d processes/%s") % m_dqm_path % procs % "all_endpaths_byluminosity").str() )->getTProfile();
00601     m_dqm_nproc_byluminosity_interpaths   = m_dqms->get( (boost::format("%s/Running %d processes/%s") % m_dqm_path % procs % "interpaths_byluminosity"  ).str() )->getTProfile();
00602   }
00603 }
00604 
00605 void FastTimerService::postEndJob() {
00606   //edm::LogImportant("FastTimerService") << __func__ << "()";
00607 
00608   if (m_enable_timing_summary) {
00609     // print a timing sumary for the whle job
00610     edm::service::TriggerNamesService & tns = * edm::Service<edm::service::TriggerNamesService>();
00611 
00612     std::ostringstream out;
00613     out << std::fixed << std::setprecision(6);
00614     out << "FastReport " << (m_timer_id == CLOCK_REALTIME ? "(real time) " : "(CPU time)  ") << '\n';
00615     out << "FastReport              " << std::right << std::setw(10) << m_summary_source       / (double) m_summary_events << "  Source"        << '\n';
00616     out << "FastReport              " << std::right << std::setw(10) << m_summary_event        / (double) m_summary_events << "  Event"         << '\n';
00617     out << "FastReport              " << std::right << std::setw(10) << m_summary_all_paths    / (double) m_summary_events << "  all Paths"     << '\n';
00618     out << "FastReport              " << std::right << std::setw(10) << m_summary_all_endpaths / (double) m_summary_events << "  all EndPaths"  << '\n';
00619     out << "FastReport              " << std::right << std::setw(10) << m_summary_interpaths   / (double) m_summary_events << "  between paths" << '\n';
00620     if (m_enable_timing_modules) {
00621       double modules_total = 0.;
00622       for (auto & keyval: m_modules)
00623         modules_total += keyval.second.summary_active;
00624       out << "FastReport              " << std::right << std::setw(10) << modules_total / (double) m_summary_events << "  all Modules"   << '\n';
00625     }
00626     out << '\n';
00627     if (m_enable_timing_paths and not m_enable_timing_modules) {
00628       out << "FastReport " << (m_timer_id == CLOCK_REALTIME ? "(real time) " : "(CPU time)  ")    << "     Active Path" << '\n';
00629       for (auto const & name: tns.getTrigPaths())
00630         out << "FastReport              "
00631             << std::right << std::setw(10) << m_paths[name].summary_active / (double) m_summary_events << "  "
00632             << name << '\n';
00633       out << '\n';
00634       out << "FastReport " << (m_timer_id == CLOCK_REALTIME ? "(real time) " : "(CPU time)  ")    << "     Active EndPath" << '\n';
00635       for (auto const & name: tns.getEndPaths())
00636         out << "FastReport              "
00637             << std::right << std::setw(10) << m_paths[name].summary_active / (double) m_summary_events << "  "
00638             << name << '\n';
00639     } else if (m_enable_timing_paths and m_enable_timing_modules) {
00640       out << "FastReport " << (m_timer_id == CLOCK_REALTIME ? "(real time) " : "(CPU time)  ")    << "     Active       Pre-     Inter-  Post-mods   Overhead      Total  Path" << '\n';
00641       for (auto const & name: tns.getTrigPaths()) {
00642         out << "FastReport              "
00643             << std::right << std::setw(10) << m_paths[name].summary_active        / (double) m_summary_events << " "
00644             << std::right << std::setw(10) << m_paths[name].summary_premodules    / (double) m_summary_events << " "
00645             << std::right << std::setw(10) << m_paths[name].summary_intermodules  / (double) m_summary_events << " "
00646             << std::right << std::setw(10) << m_paths[name].summary_postmodules   / (double) m_summary_events << " "
00647             << std::right << std::setw(10) << m_paths[name].summary_overhead      / (double) m_summary_events << " "
00648             << std::right << std::setw(10) << m_paths[name].summary_total         / (double) m_summary_events << "  "
00649             << name << '\n';
00650       }
00651       out << '\n';
00652       out << "FastReport " << (m_timer_id == CLOCK_REALTIME ? "(real time) " : "(CPU time)  ")    << "     Active       Pre-     Inter-  Post-mods   Overhead      Total  EndPath" << '\n';
00653       for (auto const & name: tns.getEndPaths()) {
00654         out << "FastReport              "
00655             << std::right << std::setw(10) << m_paths[name].summary_active        / (double) m_summary_events << " "
00656             << std::right << std::setw(10) << m_paths[name].summary_premodules    / (double) m_summary_events << " "
00657             << std::right << std::setw(10) << m_paths[name].summary_intermodules  / (double) m_summary_events << " "
00658             << std::right << std::setw(10) << m_paths[name].summary_postmodules   / (double) m_summary_events << " "
00659             << std::right << std::setw(10) << m_paths[name].summary_overhead      / (double) m_summary_events << " "
00660             << std::right << std::setw(10) << m_paths[name].summary_total         / (double) m_summary_events << "  "
00661             << name << '\n';
00662       }
00663     }
00664     out << '\n';
00665     if (m_enable_timing_modules) {
00666       out << "FastReport " << (m_timer_id == CLOCK_REALTIME ? "(real time) " : "(CPU time)  ")    << "     Active  Module" << '\n';
00667       for (auto & keyval: m_modules) {
00668         std::string const & label  = keyval.first;
00669         ModuleInfo  const & module = keyval.second;
00670         out << "FastReport              " << std::right << std::setw(10) << module.summary_active  / (double) m_summary_events << "  " << label << '\n';
00671       }
00672       out << "FastReport " << (m_timer_id == CLOCK_REALTIME ? "(real time) " : "(CPU time)  ")    << "     Active  Module" << '\n';
00673       out << '\n';
00674       out << "FastReport " << (m_timer_id == CLOCK_REALTIME ? "(real time) " : "(CPU time)  ")    << "     Active  Module" << '\n';
00675       for (auto & keyval: m_moduletypes) {
00676         std::string const & label  = keyval.first;
00677         ModuleInfo  const & module = keyval.second;
00678         out << "FastReport              " << std::right << std::setw(10) << module.summary_active  / (double) m_summary_events << "  " << label << '\n';
00679       }
00680       out << "FastReport " << (m_timer_id == CLOCK_REALTIME ? "(real time) " : "(CPU time)  ")    << "     Active  Module" << '\n';
00681     }
00682     out << '\n';
00683     edm::LogVerbatim("FastReport") << out.str();
00684   }
00685 
00686   // needed for the DAQ when reconfiguring between runs
00687   reset();
00688 }
00689 
00690 void FastTimerService::reset() {
00691   // transient dqm configuration
00692   m_nproc_enabled = false;
00693   // caching
00694   m_first_path = 0;          // these are initialized at prePathBeginRun(),
00695   m_last_path = 0;           // to make sure we cache the correct pointers
00696   m_first_endpath = 0;
00697   m_last_endpath = 0;
00698   m_is_first_module = false;
00699   // per-event accounting
00700   m_event = 0.;
00701   m_source = 0.;
00702   m_all_paths = 0.;
00703   m_all_endpaths = 0.;
00704   m_interpaths = 0.;
00705   // per-job summary
00706   m_summary_events = 0;
00707   m_summary_event = 0.;
00708   m_summary_source = 0.;
00709   m_summary_all_paths = 0.;
00710   m_summary_all_endpaths = 0.;
00711   m_summary_interpaths = 0.;
00712   // DQM - the DAQ destroys and re-creates the DQM and DQMStore services at each reconfigure, so we don't need to clean them up
00713   m_dqms = 0;
00714   // event summary plots
00715   m_dqm_event = 0;
00716   m_dqm_source = 0;
00717   m_dqm_all_paths = 0;
00718   m_dqm_all_endpaths = 0;
00719   m_dqm_interpaths = 0;
00720   // event summary plots - summed over nodes with the same number of processes
00721   m_dqm_nproc_event = 0;
00722   m_dqm_nproc_source = 0;
00723   m_dqm_nproc_all_paths = 0;
00724   m_dqm_nproc_all_endpaths = 0;
00725   m_dqm_nproc_interpaths = 0;
00726   // plots by path
00727   m_dqm_paths_active_time = 0;
00728   m_dqm_paths_total_time = 0;
00729   m_dqm_paths_exclusive_time = 0;
00730   m_dqm_paths_interpaths = 0;
00731   // plots per lumisection
00732   m_dqm_byls_event = 0;
00733   m_dqm_byls_source = 0;
00734   m_dqm_byls_all_paths = 0;
00735   m_dqm_byls_all_endpaths = 0;
00736   m_dqm_byls_interpaths = 0;
00737   // plots per lumisection - summed over nodes with the same number of processes
00738   m_dqm_nproc_byls_event = 0;
00739   m_dqm_nproc_byls_source = 0;
00740   m_dqm_nproc_byls_all_paths = 0;
00741   m_dqm_nproc_byls_all_endpaths = 0;
00742   m_dqm_nproc_byls_interpaths = 0;
00743   // plots vs. instantaneous luminosity
00744   m_dqm_byluminosity_event = 0;
00745   m_dqm_byluminosity_source = 0;
00746   m_dqm_byluminosity_all_paths = 0;
00747   m_dqm_byluminosity_all_endpaths = 0;
00748   m_dqm_byluminosity_interpaths = 0;
00749   // plots vs. instantaneous luminosity - summed over nodes with the same number of processes
00750   m_dqm_nproc_byluminosity_event = 0;
00751   m_dqm_nproc_byluminosity_source = 0;
00752   m_dqm_nproc_byluminosity_all_paths = 0;
00753   m_dqm_nproc_byluminosity_all_endpaths = 0;
00754   m_dqm_nproc_byluminosity_interpaths = 0;
00755   // per-path and per-module accounting
00756   m_current_path = 0;
00757   m_paths.clear();          // this should destroy all PathInfo objects and Reset the associated plots
00758   m_modules.clear();        // this should destroy all ModuleInfo objects and Reset the associated plots
00759   m_moduletypes.clear();    // this should destroy all ModuleInfo objects and Reset the associated plots
00760   m_fast_modules.clear();
00761   m_fast_moduletypes.clear();
00762 }
00763 
00764 void FastTimerService::preModuleBeginJob(edm::ModuleDescription const & module) {
00765   //edm::LogImportant("FastTimerService") << __func__ << "(" << & module << ")";
00766   //edm::LogImportant("FastTimerService") << "module type " << module.moduleName() << " label " << module.moduleLabel() << " @ " << & module;
00767 
00768   // allocate a counter for each module and module type
00769   m_fast_modules[& module]     = & m_modules[module.moduleLabel()];;
00770   m_fast_moduletypes[& module] = & m_moduletypes[module.moduleName()];
00771 }
00772 
00773 void FastTimerService::preProcessEvent(edm::EventID const & id, edm::Timestamp const & stamp) {
00774   //edm::LogImportant("FastTimerService") << __func__ << "(...)";
00775 
00776   // new event, reset the per-event counter
00777   start(m_timer_event);
00778 
00779   // clear the event counters
00780   m_event        = 0;
00781   m_all_paths    = 0;
00782   m_all_endpaths = 0;
00783   m_interpaths   = 0;
00784   for (auto & keyval : m_paths) {
00785     keyval.second.time_active       = 0.;
00786     keyval.second.time_premodules   = 0.;
00787     keyval.second.time_intermodules = 0.;
00788     keyval.second.time_postmodules  = 0.;
00789     keyval.second.time_total        = 0.;
00790   }
00791   for (auto & keyval : m_modules) {
00792     keyval.second.time_active       = 0.;
00793     keyval.second.has_just_run      = false;
00794     keyval.second.is_exclusive      = false;
00795   }
00796   for (auto & keyval : m_moduletypes) {
00797     keyval.second.time_active       = 0.;
00798     keyval.second.has_just_run      = false;
00799     keyval.second.is_exclusive      = false;
00800   }
00801 
00802   // copy the start event timestamp as the end of the previous path
00803   // used by the inter-path overhead measurement
00804   m_timer_path.second = m_timer_event.first;
00805 }
00806 
00807 void FastTimerService::postProcessEvent(edm::Event const & event, edm::EventSetup const & setup) {
00808   //edm::LogImportant("FastTimerService") << __func__ << "(...)";
00809 
00810   if (m_enable_timing_exclusive) {
00811     for (auto & keyval: m_paths) {
00812       PathInfo & pathinfo = keyval.second;
00813       float exclusive = pathinfo.time_overhead;
00814 
00815       for (uint32_t i = 0; i <= pathinfo.last_run; ++i) {
00816         ModuleInfo * module = pathinfo.modules[i];
00817         if (module == 0)
00818           // this is a module occurring more than once in the same path, skip it after the first occurrence
00819           continue;
00820         if (module->is_exclusive)
00821           exclusive += module->time_active;
00822       }
00823       m_dqm_paths_exclusive_time->Fill(pathinfo.index, exclusive * 1000.);
00824       if (m_enable_dqm_bypath_exclusive) {
00825         pathinfo.dqm_exclusive->Fill(exclusive * 1000.);
00826       }
00827     }
00828   }
00829 
00830   // fill plots for per-event time by module
00831   if (m_dqms and m_enable_dqm_bymodule) {
00832     for (auto & keyval : m_modules) {
00833       ModuleInfo & module = keyval.second;
00834       module.dqm_active->Fill(module.time_active * 1000.);
00835     }
00836   }
00837   // fill plots for per-event time by module type
00838   if (m_dqms and m_enable_dqm_bymoduletype) {
00839     for (auto & keyval : m_moduletypes) {
00840       ModuleInfo & module = keyval.second;
00841       module.dqm_active->Fill(module.time_active * 1000.);
00842     }
00843   }
00844 
00845   // stop the per-event timer, and account event time
00846   stop(m_timer_event);
00847   m_event = delta(m_timer_event);
00848   m_summary_event += m_event;
00849   // the last part of inter-path overhead is the time between the end of the last (end)path and the end of the event processing
00850   double interpaths = delta(m_timer_path.second, m_timer_event.second);
00851   m_interpaths += interpaths;
00852   m_summary_interpaths += m_interpaths;
00853   if (m_dqms) {
00854     m_dqm_paths_interpaths->Fill(m_paths.size(), interpaths * 1000.);
00855     
00856     if (m_enable_dqm_summary) {
00857       m_dqm_event         ->Fill(m_event          * 1000.);
00858       m_dqm_source        ->Fill(m_source         * 1000.);
00859       m_dqm_all_paths     ->Fill(m_all_paths      * 1000.);
00860       m_dqm_all_endpaths  ->Fill(m_all_endpaths   * 1000.);
00861       m_dqm_interpaths    ->Fill(m_interpaths     * 1000.);
00862 
00863       if (m_nproc_enabled) {
00864         m_dqm_nproc_event         ->Fill(m_event          * 1000.);
00865         m_dqm_nproc_source        ->Fill(m_source         * 1000.);
00866         m_dqm_nproc_all_paths     ->Fill(m_all_paths      * 1000.);
00867         m_dqm_nproc_all_endpaths  ->Fill(m_all_endpaths   * 1000.);
00868         m_dqm_nproc_interpaths    ->Fill(m_interpaths     * 1000.);
00869       }
00870     }
00871 
00872     if (m_enable_dqm_byls) {
00873       unsigned int ls = event.getLuminosityBlock().luminosityBlock();
00874       m_dqm_byls_event        ->Fill(ls, m_event        * 1000.);
00875       m_dqm_byls_source       ->Fill(ls, m_source       * 1000.);
00876       m_dqm_byls_all_paths    ->Fill(ls, m_all_paths    * 1000.);
00877       m_dqm_byls_all_endpaths ->Fill(ls, m_all_endpaths * 1000.);
00878       m_dqm_byls_interpaths   ->Fill(ls, m_interpaths   * 1000.);
00879       
00880       if (m_nproc_enabled) {
00881         m_dqm_nproc_byls_event        ->Fill(ls, m_event        * 1000.);
00882         m_dqm_nproc_byls_source       ->Fill(ls, m_source       * 1000.);
00883         m_dqm_nproc_byls_all_paths    ->Fill(ls, m_all_paths    * 1000.);
00884         m_dqm_nproc_byls_all_endpaths ->Fill(ls, m_all_endpaths * 1000.);
00885         m_dqm_nproc_byls_interpaths   ->Fill(ls, m_interpaths   * 1000.);
00886       }
00887     }
00888 
00889     if (m_enable_dqm_byluminosity) {
00890       float luminosity = 0.;
00891       edm::Handle<LumiScalersCollection> h_luminosity;
00892       if (event.getByLabel(m_luminosity_label, h_luminosity) and not h_luminosity->empty())
00893         luminosity = h_luminosity->front().instantLumi();   // in units of 1e30 cm-2s-1
00894 
00895       m_dqm_byluminosity_event        ->Fill(luminosity, m_event        * 1000.);
00896       m_dqm_byluminosity_source       ->Fill(luminosity, m_source       * 1000.);
00897       m_dqm_byluminosity_all_paths    ->Fill(luminosity, m_all_paths    * 1000.);
00898       m_dqm_byluminosity_all_endpaths ->Fill(luminosity, m_all_endpaths * 1000.);
00899       m_dqm_byluminosity_interpaths   ->Fill(luminosity, m_interpaths   * 1000.);
00900       
00901       if (m_nproc_enabled) {
00902         m_dqm_nproc_byluminosity_event        ->Fill(luminosity, m_event        * 1000.);
00903         m_dqm_nproc_byluminosity_source       ->Fill(luminosity, m_source       * 1000.);
00904         m_dqm_nproc_byluminosity_all_paths    ->Fill(luminosity, m_all_paths    * 1000.);
00905         m_dqm_nproc_byluminosity_all_endpaths ->Fill(luminosity, m_all_endpaths * 1000.);
00906         m_dqm_nproc_byluminosity_interpaths   ->Fill(luminosity, m_interpaths   * 1000.);
00907       }
00908     }
00909   }
00910 }
00911 
00912 void FastTimerService::preSource() {
00913   //edm::LogImportant("FastTimerService") << __func__ << "()";
00914 
00915   start(m_timer_source);
00916 
00917   // clear the event counters
00918   m_source = 0;
00919 
00920   // keep track of the total number of events
00921   ++m_summary_events;
00922 }
00923 
00924 void FastTimerService::postSource() {
00925   //edm::LogImportant("FastTimerService") << __func__ << "()";
00926 
00927   stop(m_timer_source);
00928   m_source = delta(m_timer_source);
00929   m_summary_source += m_source;
00930 }
00931 
00932 void FastTimerService::prePathBeginRun(std::string const & path ) {
00933   //edm::LogImportant("FastTimerService") << __func__ << "(" << path << ")";
00934 
00935   // cache the pointers to the names of the first and last path and endpath
00936   edm::service::TriggerNamesService & tns = * edm::Service<edm::service::TriggerNamesService>();
00937   if (not m_skip_first_path and not tns.getTrigPaths().empty()) {
00938     if (path == tns.getTrigPaths().front())
00939       m_first_path = & path;
00940     if (path == tns.getTrigPaths().back())
00941       m_last_path = & path;
00942   }
00943   else if (m_skip_first_path and tns.getTrigPaths().size() > 1) {
00944     if (path == tns.getTrigPaths().at(1))
00945       m_first_path = & path;
00946     if (path == tns.getTrigPaths().back())
00947       m_last_path = & path;
00948   }
00949   if (not tns.getEndPaths().empty()) {
00950     if (path == tns.getEndPaths().front())
00951       m_first_endpath = & path;
00952     if (path == tns.getEndPaths().back())
00953       m_last_endpath = & path;
00954   }
00955 }
00956 
00957 void FastTimerService::preProcessPath(std::string const & path ) {
00958   //edm::LogImportant("FastTimerService") << __func__ << "(" << path << ")";
00959 
00960   // prepare to measure the time spent between the beginning of the path and the execution of the first module
00961   m_is_first_module = true;
00962 
00963   PathMap<PathInfo>::iterator keyval = m_paths.find(path);
00964   if (keyval != m_paths.end()) {
00965     m_current_path = & keyval->second;
00966 
00967     if (m_enable_timing_modules) {
00968       // reset the status of this path's modules
00969       for (ModuleInfo * module: m_current_path->modules)
00970         if (module)
00971           module->has_just_run = false;
00972     }
00973   } else {
00974     // should never get here
00975     m_current_path = 0;
00976     edm::LogError("FastTimerService") << "FastTimerService::preProcessPath: unexpected path " << path;
00977   }
00978 
00979   // time each (end)path
00980   start(m_timer_path);
00981 
00982   if (& path == m_first_path) {
00983     // this is the first path, start the "all paths" counter
00984     m_timer_paths.first = m_timer_path.first;
00985   } else if (& path == m_first_endpath) {
00986     // this is the first endpath, start the "all paths" counter
00987     m_timer_endpaths.first = m_timer_path.first;
00988   }
00989 
00990   // measure the inter-path overhead as the time elapsed since the end of preiovus path
00991   // (or the beginning of the event, if this is the first path - see preProcessEvent)
00992   double interpaths = delta(m_timer_path.second,  m_timer_path.first);
00993   m_interpaths += interpaths;
00994   if (m_dqms) {
00995     m_dqm_paths_interpaths->Fill(m_current_path->index, interpaths * 1000.);
00996   }
00997 }
00998 
00999 void FastTimerService::postProcessPath(std::string const & path, edm::HLTPathStatus const & status) {
01000   //edm::LogImportant("FastTimerService") << __func__ << "(" << path << ", ...)";
01001 
01002   // time each (end)path
01003   stop(m_timer_path);
01004 
01005   double active = delta(m_timer_path);
01006 
01007   // if enabled, account each (end)path
01008   if (m_enable_timing_paths) {
01009 
01010     PathInfo & pathinfo = * m_current_path;
01011     pathinfo.time_active = active;
01012     pathinfo.summary_active += active;
01013 
01014     if (m_dqms) {
01015       m_dqm_paths_active_time->Fill(pathinfo.index, active * 1000.);
01016       if (m_enable_dqm_bypath_active) {
01017         pathinfo.dqm_active->Fill(active * 1000.);
01018       }
01019     }
01020 
01021     // measure the time spent between the execution of the last module and the end of the path
01022     if (m_enable_timing_modules) {
01023       double pre      = 0.;                 // time spent before the first active module
01024       double inter    = 0.;                 // time spent between active modules
01025       double post     = 0.;                 // time spent after the last active module
01026       double overhead = 0.;                 // time spent before, between, or after modules
01027       double current  = 0.;                 // time spent in modules active in the current path
01028       double total    = active;             // total per-path time, including modules already run as part of other paths
01029 
01030       // implementation note:
01031       // "active"   has already measured all the time spent in this path
01032       // "current"  will be the sum of the time spent inside each module while running this path, so that
01033       // "overhead" will be active - current
01034       // "total"    will be active + the sum of the time spent in non-active modules
01035 
01036       uint32_t last_run = status.index();     // index of the last module run in this path
01037       for (uint32_t i = 0; i <= last_run; ++i) {
01038         ModuleInfo * module = pathinfo.modules[i];
01039 
01040         // fill counter histograms - also for duplicate modules, to properly extract rejection information
01041         if (m_enable_dqm_bypath_counters) {
01042           pathinfo.dqm_module_counter->Fill(i);
01043         }
01044         
01045         if (module == 0)
01046           // this is a module occurring more than once in the same path, skip it after the first occurrence
01047           continue;
01048 
01049         if (module->has_just_run) {
01050           current += module->time_active;
01051           module->is_exclusive = true;
01052         } else {
01053           total   += module->time_active;
01054           module->is_exclusive = false;
01055         }
01056 
01057         // fill detailed timing histograms
01058         if (m_enable_dqm_bypath_details) {
01059           // fill the total time for all non-duplicate modules
01060           pathinfo.dqm_module_total->Fill(i, module->time_active * 1000.);
01061           if (module->has_just_run) {
01062             // fill the active time only for module actually running in this path
01063             pathinfo.dqm_module_active->Fill(i, module->time_active * 1000.);
01064           }
01065         }
01066 
01067       }
01068 
01069       if (status.accept())
01070         if (m_enable_dqm_bypath_counters) {
01071           pathinfo.dqm_module_counter->Fill(pathinfo.modules.size());
01072         }
01073 
01074       if (m_is_first_module) {
01075         // no modules were active during this path, account all the time as overhead
01076         pre      = 0.;
01077         inter    = 0.;
01078         post     = active;
01079         overhead = active;
01080       } else {
01081         // extract overhead information
01082         pre      = delta(m_timer_path.first,    m_timer_first_module);
01083         post     = delta(m_timer_module.second, m_timer_path.second);
01084         inter    = active - pre - current - post;
01085         // take care of numeric precision and rounding errors - the timer is less precise than nanosecond resolution
01086         if (std::abs(inter) < 1e-9)
01087           inter = 0.;
01088         overhead = active - current;
01089         // take care of numeric precision and rounding errors - the timer is less precise than nanosecond resolution
01090         if (std::abs(overhead) < 1e-9)
01091           overhead = 0.;
01092       }
01093 
01094       pathinfo.time_premodules       = pre;
01095       pathinfo.time_intermodules     = inter;
01096       pathinfo.time_postmodules      = post;
01097       pathinfo.time_overhead         = overhead;
01098       pathinfo.time_total            = total;
01099       pathinfo.summary_premodules   += pre;
01100       pathinfo.summary_intermodules += inter;
01101       pathinfo.summary_postmodules  += post;
01102       pathinfo.summary_overhead     += overhead;
01103       pathinfo.summary_total        += total;
01104       pathinfo.last_run              = last_run;
01105       if (m_dqms) {
01106         if (m_enable_dqm_bypath_overhead) {
01107           pathinfo.dqm_premodules  ->Fill(pre      * 1000.);
01108           pathinfo.dqm_intermodules->Fill(inter    * 1000.);
01109           pathinfo.dqm_postmodules ->Fill(post     * 1000.);
01110           pathinfo.dqm_overhead    ->Fill(overhead * 1000.);
01111         }
01112         m_dqm_paths_total_time->Fill(pathinfo.index, total * 1000.);
01113         if (m_enable_dqm_bypath_total) {
01114           pathinfo.dqm_total       ->Fill(total    * 1000.);
01115         }
01116       }
01117     }
01118   }
01119 
01120   if (& path == m_last_path) {
01121     // this is the last path, stop and account the "all paths" counter
01122     m_timer_paths.second = m_timer_path.second;
01123     m_all_paths = delta(m_timer_paths);
01124     m_summary_all_paths += m_all_paths;
01125   } else if (& path == m_last_endpath) {
01126     // this is the last endpath, stop and account the "all endpaths" counter
01127     m_timer_endpaths.second = m_timer_path.second;
01128     m_all_endpaths = delta(m_timer_endpaths);
01129     m_summary_all_endpaths += m_all_endpaths;
01130   }
01131 
01132 }
01133 
01134 void FastTimerService::preModule(edm::ModuleDescription const & module) {
01135   //edm::LogImportant("FastTimerService") << __func__ << "(" << & module << ")";
01136 
01137   // this is ever called only if m_enable_timing_modules = true
01138   assert(m_enable_timing_modules);
01139 
01140   // time each module
01141   start(m_timer_module);
01142 
01143   if (m_is_first_module) {
01144     m_is_first_module = false;
01145 
01146     // measure the time spent between the beginning of the path and the execution of the first module
01147     m_timer_first_module = m_timer_module.first;
01148   } 
01149 }
01150 
01151 void FastTimerService::postModule(edm::ModuleDescription const & module) {
01152   //edm::LogImportant("FastTimerService") << __func__ << "(" << & module << ")";
01153 
01154   // this is ever called only if m_enable_timing_modules = true
01155   assert(m_enable_timing_modules);
01156 
01157   // time and account each module
01158   stop(m_timer_module);
01159 
01160   { // if-scope
01161     ModuleMap<ModuleInfo*>::iterator keyval = m_fast_modules.find(& module);
01162     if (keyval != m_fast_modules.end()) {
01163       double time = delta(m_timer_module);
01164       ModuleInfo & module = * keyval->second;
01165       module.has_just_run    = true;
01166       module.time_active     = time;
01167       module.summary_active += time;
01168       // plots are filled post event processing
01169     } else {
01170       // should never get here
01171       edm::LogError("FastTimerService") << "FastTimerService::postModule: unexpected module " << module.moduleLabel();
01172     }
01173   }
01174 
01175   { // if-scope
01176     ModuleMap<ModuleInfo*>::iterator keyval = m_fast_moduletypes.find(& module);
01177     if (keyval != m_fast_moduletypes.end()) {
01178       double time = delta(m_timer_module);
01179       ModuleInfo & module = * keyval->second;
01180       // module.has_just_run is not useful here
01181       module.time_active    += time;
01182       module.summary_active += time;
01183       // plots are filled post event processing
01184     } else {
01185       // should never get here
01186       edm::LogError("FastTimerService") << "FastTimerService::postModule: unexpected module " << module.moduleLabel();
01187     }
01188   }
01189 
01190 }
01191 
01192 // associate to a path all the modules it contains
01193 void FastTimerService::fillPathMap(std::string const & name, std::vector<std::string> const & modules) {
01194   std::vector<ModuleInfo *> & pathmap = m_paths[name].modules;
01195   pathmap.clear();
01196   pathmap.reserve( modules.size() );
01197   std::unordered_set<ModuleInfo const *> pool;        // keep track of inserted modules
01198   for (auto const & module: modules) {
01199     // fix the name of negated or ignored modules
01200     std::string const & label = (module[0] == '!' or module[0] == '-') ? module.substr(1) : module;
01201 
01202     auto const & it = m_modules.find(label);
01203     if (it == m_modules.end()) {
01204       // no matching module was found
01205       pathmap.push_back( 0 );
01206     } else if (pool.insert(& it->second).second) {
01207       // new module
01208       pathmap.push_back(& it->second);
01209     } else {
01210       // duplicate module
01211       pathmap.push_back( 0 );
01212     }
01213 
01214   }
01215 }
01216 
01217 
01218 // query the current module/path/event
01219 // Note: these functions incur in a "per-call timer overhead" (see above), currently of the order of 340ns
01220 
01221 // return the time spent since the last preModule() event
01222 double FastTimerService::currentModuleTime() const {
01223   struct timespec now;
01224   gettime(now);
01225   return delta(m_timer_module.first, now);
01226 }
01227 
01228 // return the time spent since the last preProcessPath() event
01229 double FastTimerService::currentPathTime() const {
01230   struct timespec now;
01231   gettime(now);
01232   return delta(m_timer_path.first, now);
01233 }
01234 
01235 // return the time spent since the last preProcessEvent() event
01236 double FastTimerService::currentEventTime() const {
01237   struct timespec now;
01238   gettime(now);
01239   return delta(m_timer_event.first, now);
01240 }
01241 
01242 // query the time spent in a module (available after the module has run)
01243 double FastTimerService::queryModuleTime(const edm::ModuleDescription & module) const {
01244   ModuleMap<ModuleInfo *>::const_iterator keyval = m_fast_modules.find(& module);
01245   if (keyval != m_fast_modules.end()) {
01246     return keyval->second->time_active;
01247   } else {
01248     edm::LogError("FastTimerService") << "FastTimerService::queryModuleTime: unexpected module " << module.moduleLabel();
01249     return 0.;
01250   }
01251 }
01252 
01253 // query the time spent in a module (available after the module has run
01254 double FastTimerService::queryModuleTimeByLabel(const std::string & label) const {
01255   auto const & keyval = m_modules.find(label);
01256   if (keyval != m_modules.end()) {
01257     return keyval->second.time_active;
01258   } else {
01259     // module not found
01260     edm::LogError("FastTimerService") << "FastTimerService::queryModuleTimeByLabel: unexpected module " << label;
01261     return 0.;
01262   }
01263 }
01264 
01265 // query the time spent in a module (available after the module has run
01266 double FastTimerService::queryModuleTimeByType(const std::string & type) const {
01267   auto const & keyval = m_moduletypes.find(type);
01268   if (keyval != m_moduletypes.end()) {
01269     return keyval->second.time_active;
01270   } else {
01271     // module not found
01272     edm::LogError("FastTimerService") << "FastTimerService::queryModuleTimeByType: unexpected module type " << type;
01273     return 0.;
01274   }
01275 }
01276 
01277 // query the time spent in a path (available after the path has run)
01278 double FastTimerService::queryPathActiveTime(const std::string & path) const {
01279   PathMap<PathInfo>::const_iterator keyval = m_paths.find(path);
01280   if (keyval != m_paths.end()) {
01281     return keyval->second.time_active;
01282   } else {
01283     edm::LogError("FastTimerService") << "FastTimerService::queryPathActiveTime: unexpected path " << path;
01284     return 0.;
01285   }
01286 }
01287 
01288 // query the total time spent in a path (available after the path has run)
01289 double FastTimerService::queryPathTotalTime(const std::string & path) const {
01290   PathMap<PathInfo>::const_iterator keyval = m_paths.find(path);
01291   if (keyval != m_paths.end()) {
01292     return keyval->second.time_total;
01293   } else {
01294     edm::LogError("FastTimerService") << "FastTimerService::queryPathTotalTime: unexpected path " << path;
01295     return 0.;
01296   }
01297 }
01298 
01299 // query the time spent in the current event's source (available during event processing)
01300 double FastTimerService::querySourceTime() const {
01301   return m_source;
01302 }
01303 
01304 // query the time spent in the current event's paths (available during endpaths)
01305 double FastTimerService::queryPathsTime() const {
01306   return m_all_paths;
01307 }
01308 
01309 // query the time spent in the current event's endpaths (available after all endpaths have run)
01310 double FastTimerService::queryEndPathsTime() const {
01311   return m_all_endpaths;
01312 }
01313 
01314 // query the time spent processing the current event (available after the event has been processed)
01315 double FastTimerService::queryEventTime() const {
01316   return m_event;
01317 }
01318 
01319 // describe the module's configuration
01320 void FastTimerService::fillDescriptions(edm::ConfigurationDescriptions & descriptions) {
01321   edm::ParameterSetDescription desc;
01322   desc.addUntracked<bool>(   "useRealTimeClock",         true);
01323   desc.addUntracked<bool>(   "enableTimingPaths",        true);
01324   desc.addUntracked<bool>(   "enableTimingModules",      true);
01325   desc.addUntracked<bool>(   "enableTimingExclusive",    false);
01326   desc.addUntracked<bool>(   "enableTimingSummary",      false);
01327   desc.addUntracked<bool>(   "skipFirstPath",            false), 
01328   desc.addUntracked<bool>(   "enableDQM",                true);
01329   desc.addUntracked<bool>(   "enableDQMbyPathActive",    false);
01330   desc.addUntracked<bool>(   "enableDQMbyPathTotal",     true);
01331   desc.addUntracked<bool>(   "enableDQMbyPathOverhead",  false);
01332   desc.addUntracked<bool>(   "enableDQMbyPathDetails",   false);
01333   desc.addUntracked<bool>(   "enableDQMbyPathCounters",  true);
01334   desc.addUntracked<bool>(   "enableDQMbyPathExclusive", false);
01335   desc.addUntracked<bool>(   "enableDQMbyModule",        false);
01336   desc.addUntracked<bool>(   "enableDQMbyModuleType",    false);
01337   desc.addUntracked<bool>(   "enableDQMSummary",         false);
01338   desc.addUntracked<bool>(   "enableDQMbyLuminosity",    false);
01339   desc.addNode(
01340     edm::ParameterDescription<bool>(   "enableDQMbyLumiSection", false, false) or
01341     edm::ParameterDescription<bool>(   "enableDQMbyLumi",        false, false)
01342   );
01343   desc.addUntracked<bool>(   "enableDQMbyProcesses",     false);
01344   desc.addUntracked<double>( "dqmTimeRange",             1000. );   // ms
01345   desc.addUntracked<double>( "dqmTimeResolution",           5. );   // ms
01346   desc.addUntracked<double>( "dqmPathTimeRange",          100. );   // ms
01347   desc.addUntracked<double>( "dqmPathTimeResolution",       0.5);   // ms
01348   desc.addUntracked<double>( "dqmModuleTimeRange",         40. );   // ms
01349   desc.addUntracked<double>( "dqmModuleTimeResolution",     0.2);   // ms
01350   desc.addUntracked<double>( "dqmLuminosityRange",      1.e34  );   // cm-2 s-1
01351   desc.addUntracked<double>( "dqmLuminosityResolution", 1.e31  );   // cm-2 s-1
01352   desc.addUntracked<uint32_t>( "dqmLumiSectionsRange",   2500  );   // ~ 16 hours
01353   desc.addUntracked<std::string>(   "dqmPath",           "HLT/TimerService");
01354   desc.addUntracked<edm::InputTag>( "luminosityProduct", edm::InputTag("hltScalersRawToDigi"));
01355   desc.addUntracked<std::vector<unsigned int> >("supportedProcesses", { 8, 24, 32 });
01356   descriptions.add("FastTimerService", desc);
01357 }