CMS 3D CMS Logo

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