CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_6/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 <tr1/unordered_set>
00024 #include <tr1/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 "DQMServices/Core/interface/DQMStore.h"
00044 #include "DQMServices/Core/interface/MonitorElement.h"
00045 #include "HLTrigger/Timer/interface/FastTimerService.h"
00046 #include "HLTrigger/Timer/interface/CPUAffinity.h"
00047 
00048 
00049 // file-static methods to fill a vector of strings with "(dup.) (...)" entries
00050 static
00051 void fill_dups(std::vector<std::string> & dups, unsigned int size) {
00052   dups.reserve(size);
00053   for (unsigned int i = dups.size(); i < size; ++i)
00054     dups.push_back( (boost::format("(dup.) (%d)") % i).str() );
00055 }
00056 
00057 
00058 FastTimerService::FastTimerService(const edm::ParameterSet & config, edm::ActivityRegistry & registry) :
00059   // configuration
00060   m_timer_id(                   config.getUntrackedParameter<bool>(    "useRealTimeClock"         ) ? CLOCK_REALTIME : CLOCK_THREAD_CPUTIME_ID),
00061   m_is_cpu_bound(               false ),
00062   m_enable_timing_paths(        config.getUntrackedParameter<bool>(    "enableTimingPaths"        ) ),
00063   m_enable_timing_modules(      config.getUntrackedParameter<bool>(    "enableTimingModules"      ) ),
00064   m_enable_timing_exclusive(    config.getUntrackedParameter<bool>(    "enableTimingExclusive"    ) ),
00065   m_enable_timing_summary(      config.getUntrackedParameter<bool>(    "enableTimingSummary"      ) ),
00066   m_skip_first_path(            config.getUntrackedParameter<bool>(    "skipFirstPath"            ) ),
00067   // dqm configuration
00068   m_enable_dqm(                  config.getUntrackedParameter<bool>(   "enableDQM"                ) ),
00069   m_enable_dqm_bypath_active(    config.getUntrackedParameter<bool>(   "enableDQMbyPathActive"    ) ),
00070   m_enable_dqm_bypath_total(     config.getUntrackedParameter<bool>(   "enableDQMbyPathTotal"     ) ),
00071   m_enable_dqm_bypath_overhead(  config.getUntrackedParameter<bool>(   "enableDQMbyPathOverhead"  ) ),
00072   m_enable_dqm_bypath_details(   config.getUntrackedParameter<bool>(   "enableDQMbyPathDetails"   ) ),
00073   m_enable_dqm_bypath_counters(  config.getUntrackedParameter<bool>(   "enableDQMbyPathCounters"  ) ),
00074   m_enable_dqm_bypath_exclusive( config.getUntrackedParameter<bool>(   "enableDQMbyPathExclusive" ) ),
00075   m_enable_dqm_bymodule(         config.getUntrackedParameter<bool>(   "enableDQMbyModule"        ) ),
00076   m_enable_dqm_bylumi(           config.getUntrackedParameter<bool>(   "enableDQMbyLumi"          ) ),
00077   m_dqm_eventtime_range(         config.getUntrackedParameter<double>( "dqmTimeRange"             ) ),    // ms
00078   m_dqm_eventtime_resolution(    config.getUntrackedParameter<double>( "dqmTimeResolution"        ) ),    // ms
00079   m_dqm_pathtime_range(          config.getUntrackedParameter<double>( "dqmPathTimeRange"         ) ),    // ms
00080   m_dqm_pathtime_resolution(     config.getUntrackedParameter<double>( "dqmPathTimeResolution"    ) ),    // ms
00081   m_dqm_moduletime_range(        config.getUntrackedParameter<double>( "dqmModuleTimeRange"       ) ),    // ms
00082   m_dqm_moduletime_resolution(   config.getUntrackedParameter<double>( "dqmModuleTimeResolution"  ) ),    // ms
00083   m_dqm_lumi_range(              config.getUntrackedParameter<uint32_t>( "dqmLumiSectionsRange"   ) ),    // lumisections
00084   m_dqm_path(                    config.getUntrackedParameter<std::string>("dqmPath" ) ),
00085   // caching
00086   m_first_path(0),          // these are initialized at prePathBeginRun(),
00087   m_last_path(0),           // to make sure we cache the correct pointers
00088   m_first_endpath(0),
00089   m_last_endpath(0),
00090   m_is_first_module(false),
00091   // per-event accounting
00092   m_event(0.),
00093   m_source(0.),
00094   m_all_paths(0.),
00095   m_all_endpaths(0.),
00096   // per-job summary
00097   m_summary_events(0),
00098   m_summary_event(0.),
00099   m_summary_source(0.),
00100   m_summary_all_paths(0.),
00101   m_summary_all_endpaths(0.),
00102   // DQM
00103   m_dqms(0),                // these are initialized at postBeginJob(),
00104   m_dqm_event(0),           // to make sure the DQM service has been loaded
00105   m_dqm_source(0),
00106   m_dqm_all_paths(0),
00107   m_dqm_all_endpaths(0),
00108   m_dqm_paths_active_time(0),
00109   m_dqm_paths_total_time(0),
00110   m_dqm_paths_exclusive_time(0),
00111   // per-lumisection plots
00112   m_dqm_bylumi_event(0),
00113   m_dqm_bylumi_source(0),
00114   m_dqm_bylumi_all_paths(0),
00115   m_dqm_bylumi_all_endpaths(0),
00116   // per-path and per-module accounting
00117   m_current_path(0),
00118   m_paths(),
00119   m_modules(),
00120   m_cache_paths(),
00121   m_cache_modules()
00122 {
00123   // enable timers if required by DQM plots
00124   m_enable_timing_paths     = m_enable_timing_paths     or m_enable_dqm_bypath_active or m_enable_dqm_bypath_total or m_enable_dqm_bypath_overhead or m_enable_dqm_bypath_details or m_enable_dqm_bypath_counters or m_enable_dqm_bypath_exclusive;
00125   m_enable_timing_modules   = m_enable_timing_modules   or m_enable_dqm_bymodule      or m_enable_dqm_bypath_total or m_enable_dqm_bypath_overhead or m_enable_dqm_bypath_details or m_enable_dqm_bypath_counters or m_enable_dqm_bypath_exclusive;
00126   m_enable_timing_exclusive = m_enable_timing_exclusive or m_enable_dqm_bypath_exclusive;
00127 
00128   registry.watchPreModuleBeginJob( this, & FastTimerService::preModuleBeginJob );
00129   registry.watchPostBeginJob(      this, & FastTimerService::postBeginJob );
00130   registry.watchPostEndJob(        this, & FastTimerService::postEndJob );
00131   registry.watchPrePathBeginRun(   this, & FastTimerService::prePathBeginRun) ;
00132   registry.watchPreProcessEvent(   this, & FastTimerService::preProcessEvent );
00133   registry.watchPostProcessEvent(  this, & FastTimerService::postProcessEvent );
00134   registry.watchPreSource(         this, & FastTimerService::preSource );
00135   registry.watchPostSource(        this, & FastTimerService::postSource );
00136   // watch per-path events
00137   registry.watchPreProcessPath(    this, & FastTimerService::preProcessPath );
00138   registry.watchPostProcessPath(   this, & FastTimerService::postProcessPath );
00139   // watch per-module events if enabled
00140   if (m_enable_timing_modules) {
00141     registry.watchPreModule(         this, & FastTimerService::preModule );
00142     registry.watchPostModule(        this, & FastTimerService::postModule );
00143   }
00144 
00145 #if defined(__APPLE__) || defined (__MACH__)
00146   host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &m_clock_port);
00147 #endif // defined(__APPLE__) || defined(__MACH__)
00148 }
00149 
00150 FastTimerService::~FastTimerService()
00151 {
00152 #if defined(__APPLE__) || defined (__MACH__)
00153   mach_port_deallocate(mach_task_self(), m_clock_port);
00154 #endif // defined(__APPLE__) || defined(__MACH__)
00155 }
00156 
00157 void FastTimerService::postBeginJob() {
00158   //edm::LogImportant("FastTimerService") << __func__ << "()";
00159 
00160   // check if the process is bound to a single CPU.
00161   // otherwise, the results of the CLOCK_THREAD_CPUTIME_ID timer might be inaccurate
00162   m_is_cpu_bound = CPUAffinity::isCpuBound();
00163   if ((m_timer_id != CLOCK_REALTIME) and not m_is_cpu_bound)
00164     // the process is NOT bound to a single CPU
00165     edm::LogError("FastTimerService") << "this process is NOT bound to a single CPU, the results of the FastTimerService may be undefined";
00166 
00167   edm::service::TriggerNamesService & tns = * edm::Service<edm::service::TriggerNamesService>();
00168   uint32_t size_p = tns.getTrigPaths().size();
00169   uint32_t size_e = tns.getEndPaths().size();
00170   uint32_t size = size_p + size_e;
00171   for (uint32_t i = 0; i < size_p; ++i) {
00172     std::string const & label = tns.getTrigPath(i);
00173     m_paths[label].index = i;
00174   }
00175   for (uint32_t i = 0; i < size_e; ++i) {
00176     std::string const & label = tns.getEndPath(i);
00177     m_paths[label].index = size_p + i;
00178   }
00179 
00180   // cache all pathinfo objects
00181   m_cache_paths.reserve(m_paths.size());
00182   for (auto & keyval: m_paths)
00183     m_cache_paths.push_back(& keyval.second);
00184 
00185   // cache all moduleinfo objects
00186   m_cache_modules.reserve(m_modules.size());
00187   for (auto & keyval: m_modules)
00188     m_cache_modules.push_back(& keyval.second);
00189 
00190   // associate to each path all the modules it contains
00191   for (uint32_t i = 0; i < tns.getTrigPaths().size(); ++i)
00192     fillPathMap( tns.getTrigPath(i), tns.getTrigPathModules(i) );
00193   for (uint32_t i = 0; i < tns.getEndPaths().size(); ++i)
00194     fillPathMap( tns.getEndPath(i), tns.getEndPathModules(i) );
00195 
00196   if (m_enable_dqm)
00197     // load the DQM store
00198     m_dqms = edm::Service<DQMStore>().operator->();
00199 
00200   if (m_dqms) {
00201     // book MonitorElement's
00202     int eventbins  = (int) std::ceil(m_dqm_eventtime_range  / m_dqm_eventtime_resolution);
00203     int pathbins   = (int) std::ceil(m_dqm_pathtime_range   / m_dqm_pathtime_resolution);
00204     int modulebins = (int) std::ceil(m_dqm_moduletime_range / m_dqm_moduletime_resolution);
00205 
00206     m_dqms->setCurrentFolder(m_dqm_path);
00207 
00208     // event plots
00209     m_dqm_event         = m_dqms->book1D("event",        "Event processing time",    eventbins, 0., m_dqm_eventtime_range)->getTH1F();
00210     m_dqm_event         ->StatOverflows(true);
00211     m_dqm_event         ->SetXTitle("processing time [ms]");
00212     m_dqm_source        = m_dqms->book1D("source",       "Source processing time",   pathbins,  0., m_dqm_pathtime_range)->getTH1F();
00213     m_dqm_source        ->StatOverflows(true);
00214     m_dqm_source        ->SetXTitle("processing time [ms]");
00215     m_dqm_all_paths     = m_dqms->book1D("all_paths",    "Paths processing time",    eventbins, 0., m_dqm_eventtime_range)->getTH1F();
00216     m_dqm_all_paths     ->StatOverflows(true);
00217     m_dqm_all_paths     ->SetXTitle("processing time [ms]");
00218     m_dqm_all_endpaths  = m_dqms->book1D("all_endpaths", "EndPaths processing time", pathbins,  0., m_dqm_pathtime_range)->getTH1F();
00219     m_dqm_all_endpaths  ->StatOverflows(true);
00220     m_dqm_all_endpaths  ->SetXTitle("processing time [ms]");
00221 
00222     // summary plots
00223     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();
00224     m_dqm_paths_active_time     ->StatOverflows(true);
00225     m_dqm_paths_active_time     ->SetYTitle("processing time [ms]");
00226     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();
00227     m_dqm_paths_total_time      ->StatOverflows(true);
00228     m_dqm_paths_total_time      ->SetYTitle("processing time [ms]");
00229     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();
00230     m_dqm_paths_exclusive_time  ->StatOverflows(true);
00231     m_dqm_paths_exclusive_time  ->SetYTitle("processing time [ms]");
00232 
00233     for (uint32_t i = 0; i < size_p; ++i) {
00234       std::string const & label = tns.getTrigPath(i);
00235       m_dqm_paths_active_time    ->GetXaxis()->SetBinLabel(i + 1, label.c_str());
00236       m_dqm_paths_total_time     ->GetXaxis()->SetBinLabel(i + 1, label.c_str());
00237       m_dqm_paths_exclusive_time ->GetXaxis()->SetBinLabel(i + 1, label.c_str());
00238     }
00239     for (uint32_t i = 0; i < size_e; ++i) {
00240       std::string const & label = tns.getEndPath(i);
00241       m_dqm_paths_active_time    ->GetXaxis()->SetBinLabel(i + size_p + 1, label.c_str());
00242       m_dqm_paths_total_time     ->GetXaxis()->SetBinLabel(i + size_p + 1, label.c_str());
00243       m_dqm_paths_exclusive_time ->GetXaxis()->SetBinLabel(i + size_p + 1, label.c_str());
00244     }
00245 
00246     // per-lumisection plots
00247     if (m_enable_dqm_bylumi) {
00248       m_dqm_bylumi_event        = m_dqms->bookProfile("event_bylumi",        "Event processing time, by Lumisection",    m_dqm_lumi_range, 0.5, m_dqm_lumi_range+0.5, eventbins, 0., std::numeric_limits<double>::infinity(), " ")->getTProfile();
00249       m_dqm_bylumi_event        ->StatOverflows(true);
00250       m_dqm_bylumi_event        ->SetYTitle("processing time [ms]");
00251       m_dqm_bylumi_source       = m_dqms->bookProfile("source_bylumi",       "Source processing time, by Lumisection",   m_dqm_lumi_range, 0.5, m_dqm_lumi_range+0.5, pathbins,  0., std::numeric_limits<double>::infinity(), " ")->getTProfile();
00252       m_dqm_bylumi_source       ->StatOverflows(true);
00253       m_dqm_bylumi_source       ->SetYTitle("processing time [ms]");
00254       m_dqm_bylumi_all_paths    = m_dqms->bookProfile("all_paths_bylumi",    "Paths processing time, by Lumisection",    m_dqm_lumi_range, 0.5, m_dqm_lumi_range+0.5, eventbins, 0., std::numeric_limits<double>::infinity(), " ")->getTProfile();
00255       m_dqm_bylumi_all_paths    ->StatOverflows(true);
00256       m_dqm_bylumi_all_paths    ->SetYTitle("processing time [ms]");
00257       m_dqm_bylumi_all_endpaths = m_dqms->bookProfile("all_endpaths_bylumi", "EndPaths processing time, by Lumisection", m_dqm_lumi_range, 0.5, m_dqm_lumi_range+0.5, pathbins,  0., std::numeric_limits<double>::infinity(), " ")->getTProfile();
00258       m_dqm_bylumi_all_endpaths ->StatOverflows(true);
00259       m_dqm_bylumi_all_endpaths ->SetYTitle("processing time [ms]");
00260     }
00261 
00262     // per-path and per-module accounting
00263     if (m_enable_timing_paths) {
00264       m_dqms->setCurrentFolder((m_dqm_path + "/Paths"));
00265       for (auto & keyval: m_paths) {
00266         std::string const & pathname = keyval.first;
00267         PathInfo          & pathinfo = keyval.second;
00268 
00269         if (m_enable_dqm_bypath_active) {
00270           pathinfo.dqm_active       = m_dqms->book1D(pathname + "_active",       pathname + " active time",            pathbins, 0., m_dqm_pathtime_range)->getTH1F();
00271           pathinfo.dqm_active       ->StatOverflows(true);
00272           pathinfo.dqm_active       ->SetXTitle("processing time [ms]");
00273         }
00274 
00275         if (m_enable_dqm_bypath_total) {
00276           pathinfo.dqm_total        = m_dqms->book1D(pathname + "_total",        pathname + " total time",             pathbins, 0., m_dqm_pathtime_range)->getTH1F();
00277           pathinfo.dqm_total        ->StatOverflows(true);
00278           pathinfo.dqm_total        ->SetXTitle("processing time [ms]");
00279         }
00280 
00281         if (m_enable_dqm_bypath_overhead) {
00282           pathinfo.dqm_premodules   = m_dqms->book1D(pathname + "_premodules",   pathname + " pre-modules overhead",   modulebins, 0., m_dqm_moduletime_range)->getTH1F();
00283           pathinfo.dqm_premodules   ->StatOverflows(true);
00284           pathinfo.dqm_premodules   ->SetXTitle("processing time [ms]");
00285           pathinfo.dqm_intermodules = m_dqms->book1D(pathname + "_intermodules", pathname + " inter-modules overhead", modulebins, 0., m_dqm_moduletime_range)->getTH1F();
00286           pathinfo.dqm_intermodules ->StatOverflows(true);
00287           pathinfo.dqm_intermodules ->SetXTitle("processing time [ms]");
00288           pathinfo.dqm_postmodules  = m_dqms->book1D(pathname + "_postmodules",  pathname + " post-modules overhead",  modulebins, 0., m_dqm_moduletime_range)->getTH1F();
00289           pathinfo.dqm_postmodules  ->StatOverflows(true);
00290           pathinfo.dqm_postmodules  ->SetXTitle("processing time [ms]");
00291           pathinfo.dqm_overhead     = m_dqms->book1D(pathname + "_overhead",     pathname + " overhead time",          modulebins, 0., m_dqm_moduletime_range)->getTH1F();
00292           pathinfo.dqm_overhead     ->StatOverflows(true);
00293           pathinfo.dqm_overhead     ->SetXTitle("processing time [ms]");
00294         }
00295 
00296         if (m_enable_dqm_bypath_details or m_enable_dqm_bypath_counters) {
00297           // book histograms for modules-in-paths statistics
00298 
00299           // find histograms X-axis labels
00300           uint32_t id;
00301           std::vector<std::string> const & modules = ((id = tns.findTrigPath(pathname)) != tns.getTrigPaths().size()) ? tns.getTrigPathModules(id) :
00302                                                      ((id = tns.findEndPath(pathname))  != tns.getEndPaths().size())  ? tns.getEndPathModules(id)  :
00303                                                      std::vector<std::string>();
00304 
00305           static std::vector<std::string> dup;
00306           if (modules.size() > dup.size())
00307             fill_dups(dup, modules.size());
00308 
00309           std::vector<const char *> labels(modules.size(), nullptr);
00310           for (uint32_t i = 0; i < modules.size(); ++i)
00311             labels[i] = (pathinfo.modules[i]) ? modules[i].c_str() : dup[i].c_str();
00312           
00313           // book counter histograms
00314           if (m_enable_dqm_bypath_counters) {
00315             pathinfo.dqm_module_counter = m_dqms->book1D(pathname + "_module_counter", pathname + " module counter", modules.size(), -0.5, modules.size() - 0.5)->getTH1F();
00316             // find module labels
00317             for (uint32_t i = 0; i < modules.size(); ++i) {
00318               pathinfo.dqm_module_counter->GetXaxis()->SetBinLabel( i+1, labels[i] );
00319             }
00320           }
00321           // book detailed timing histograms
00322           if (m_enable_dqm_bypath_details) {
00323             pathinfo.dqm_module_active  = m_dqms->book1D(pathname + "_module_active",  pathname + " module active",  modules.size(), -0.5, modules.size() - 0.5)->getTH1F();
00324             pathinfo.dqm_module_active  ->SetYTitle("cumulative processing time [ms]");
00325             pathinfo.dqm_module_total   = m_dqms->book1D(pathname + "_module_total",   pathname + " module total",   modules.size(), -0.5, modules.size() - 0.5)->getTH1F();
00326             pathinfo.dqm_module_total   ->SetYTitle("cumulative processing time [ms]");
00327             // find module labels
00328             for (uint32_t i = 0; i < modules.size(); ++i) {
00329               pathinfo.dqm_module_active ->GetXaxis()->SetBinLabel( i+1, labels[i] );
00330               pathinfo.dqm_module_total  ->GetXaxis()->SetBinLabel( i+1, labels[i] );
00331             }
00332           }
00333         }
00334 
00335         // book exclusive path time histograms
00336         if (m_enable_dqm_bypath_exclusive) {
00337           pathinfo.dqm_exclusive = m_dqms->book1D(pathname + "_exclusive", pathname + " exclusive time", pathbins, 0., m_dqm_pathtime_range)->getTH1F();
00338           pathinfo.dqm_exclusive ->StatOverflows(true);
00339           pathinfo.dqm_exclusive ->SetYTitle("processing time [ms]");
00340         }
00341 
00342       }
00343     }
00344    
00345     if (m_enable_dqm_bymodule) {
00346       m_dqms->setCurrentFolder((m_dqm_path + "/Modules"));
00347       for (auto & keyval: m_modules) {
00348         std::string const & label  = keyval.first->moduleLabel();
00349         ModuleInfo        & module = keyval.second;
00350         module.dqm_active = m_dqms->book1D(label, label, modulebins, 0., m_dqm_moduletime_range)->getTH1F();
00351         module.dqm_active->StatOverflows(true);
00352         module.dqm_active->SetYTitle("processing time [ms]");
00353       }
00354     }
00355 
00356   }
00357 }
00358 
00359 void FastTimerService::postEndJob() {
00360   //edm::LogImportant("FastTimerService") << __func__ << "()";
00361 
00362   if (m_enable_timing_summary) {
00363     // print a timing sumary for the whle job
00364     edm::service::TriggerNamesService & tns = * edm::Service<edm::service::TriggerNamesService>();
00365 
00366     std::ostringstream out;
00367     out << std::fixed << std::setprecision(6);
00368     out << "FastReport " << (m_timer_id == CLOCK_REALTIME ? "(real time) " : "(CPU time)  ") << '\n';
00369     out << "FastReport              " << std::right << std::setw(10) << m_summary_source       / (double) m_summary_events << "  Source"        << '\n';
00370     out << "FastReport              " << std::right << std::setw(10) << m_summary_event        / (double) m_summary_events << "  Event"         << '\n';
00371     out << "FastReport              " << std::right << std::setw(10) << m_summary_all_paths    / (double) m_summary_events << "  all Paths"     << '\n';
00372     out << "FastReport              " << std::right << std::setw(10) << m_summary_all_endpaths / (double) m_summary_events << "  all EndPaths"  << '\n';
00373     if (m_enable_timing_modules) {
00374       double modules_total = 0.;
00375       for (auto & keyval: m_modules)
00376         modules_total += keyval.second.summary_active;
00377       out << "FastReport              " << std::right << std::setw(10) << modules_total          / (double) m_summary_events << "  all Modules"   << '\n';
00378     }
00379     out << '\n';
00380     if (m_enable_timing_paths and not m_enable_timing_modules) {
00381       out << "FastReport " << (m_timer_id == CLOCK_REALTIME ? "(real time) " : "(CPU time)  ")    << "     Active Path" << '\n';
00382       for (auto const & name: tns.getTrigPaths())
00383         out << "FastReport              "
00384             << std::right << std::setw(10) << m_paths[name].summary_active  / (double) m_summary_events << "  "
00385             << name << '\n';
00386       out << '\n';
00387       out << "FastReport " << (m_timer_id == CLOCK_REALTIME ? "(real time) " : "(CPU time)  ")    << "     Active EndPath" << '\n';
00388       for (auto const & name: tns.getEndPaths())
00389         out << "FastReport              "
00390             << std::right << std::setw(10) << m_paths[name].summary_active  / (double) m_summary_events << "  "
00391             << name << '\n';
00392     } else if (m_enable_timing_paths and m_enable_timing_modules) {
00393       out << "FastReport " << (m_timer_id == CLOCK_REALTIME ? "(real time) " : "(CPU time)  ")    << "     Active      Pre-    Inter- Post-mods  Overhead     Total  Path" << '\n';
00394       for (auto const & name: tns.getTrigPaths()) {
00395         out << "FastReport              "
00396             << std::right << std::setw(10) << m_paths[name].summary_active        / (double) m_summary_events << " "
00397             << std::right << std::setw(10) << m_paths[name].summary_premodules    / (double) m_summary_events << " "
00398             << std::right << std::setw(10) << m_paths[name].summary_intermodules  / (double) m_summary_events << " "
00399             << std::right << std::setw(10) << m_paths[name].summary_postmodules   / (double) m_summary_events << " "
00400             << std::right << std::setw(10) << m_paths[name].summary_overhead      / (double) m_summary_events << " "
00401             << std::right << std::setw(10) << m_paths[name].summary_total         / (double) m_summary_events << "  "
00402             << name << '\n';
00403       }
00404       out << '\n';
00405       out << "FastReport " << (m_timer_id == CLOCK_REALTIME ? "(real time) " : "(CPU time)  ")    << "     Active      Pre-    Inter- Post-mods  Overhead     Total  EndPath" << '\n';
00406       for (auto const & name: tns.getEndPaths()) {
00407         out << "FastReport              "
00408             << std::right << std::setw(10) << m_paths[name].summary_active        / (double) m_summary_events << " "
00409             << std::right << std::setw(10) << m_paths[name].summary_premodules    / (double) m_summary_events << " "
00410             << std::right << std::setw(10) << m_paths[name].summary_intermodules  / (double) m_summary_events << " "
00411             << std::right << std::setw(10) << m_paths[name].summary_postmodules   / (double) m_summary_events << " "
00412             << std::right << std::setw(10) << m_paths[name].summary_overhead      / (double) m_summary_events << " "
00413             << std::right << std::setw(10) << m_paths[name].summary_total         / (double) m_summary_events << "  "
00414             << name << '\n';
00415       }
00416     }
00417     out << '\n';
00418     if (m_enable_timing_modules) {
00419       out << "FastReport " << (m_timer_id == CLOCK_REALTIME ? "(real time) " : "(CPU time)  ")    << "     Active  Module" << '\n';
00420       for (auto & keyval: m_modules) {
00421         std::string const & label  = keyval.first->moduleLabel();
00422         ModuleInfo  const & module = keyval.second;
00423         out << "FastReport              " << std::right << std::setw(10) << module.summary_active  / (double) m_summary_events << "  " << label << '\n';
00424       }
00425       out << "FastReport " << (m_timer_id == CLOCK_REALTIME ? "(real time) " : "(CPU time)  ")    << "     Active  Module" << '\n';
00426     }
00427     out << '\n';
00428     edm::LogVerbatim("FastReport") << out.str();
00429   }
00430 
00431   // needed for the DAQ when reconfiguring between runs
00432   reset();
00433 }
00434 
00435 void FastTimerService::reset() {
00436   // caching
00437   m_first_path = 0;          // these are initialized at prePathBeginRun(),
00438   m_last_path = 0;           // to make sure we cache the correct pointers
00439   m_first_endpath = 0;
00440   m_last_endpath = 0;
00441   m_is_first_module = false;
00442   // per-event accounting
00443   m_event = 0.;
00444   m_source = 0.;
00445   m_all_paths = 0.;
00446   m_all_endpaths = 0.;
00447   // per-job summary
00448   m_summary_events = 0;
00449   m_summary_event = 0.;
00450   m_summary_source = 0.;
00451   m_summary_all_paths = 0.;
00452   m_summary_all_endpaths = 0.;
00453   // DQM
00454   m_dqms = 0;
00455   // the DAQ destroys and re-creates the DQM and DQMStore services at each reconfigure, so we don't need to clean them up
00456   m_dqm_event = 0;
00457   m_dqm_source = 0;
00458   m_dqm_all_paths = 0;
00459   m_dqm_all_endpaths = 0;
00460   // per-path and per-module accounting
00461   m_current_path = 0;
00462   m_paths.clear();          // this should destroy all PathInfo objects and Reset the associated plots
00463   m_modules.clear();        // this should destroy all ModuleInfo objects and Reset the associated plots
00464   m_cache_paths.clear();
00465   m_cache_modules.clear();
00466 }
00467 
00468 void FastTimerService::preModuleBeginJob(edm::ModuleDescription const & module) {
00469   //edm::LogImportant("FastTimerService") << __func__ << "(" << & module << ")";
00470   //edm::LogImportant("FastTimerService") << "module " << module.moduleLabel() << " @ " << & module;
00471 
00472   // allocate a counter for each module
00473   m_modules[& module];
00474 }
00475 
00476 void FastTimerService::preProcessEvent(edm::EventID const & id, edm::Timestamp const & stamp) {
00477   //edm::LogImportant("FastTimerService") << __func__ << "(...)";
00478 
00479   // new event, reset the per-event counter
00480   start(m_timer_event);
00481 
00482   // clear the event counters
00483   m_event        = 0;
00484   m_all_paths    = 0;
00485   m_all_endpaths = 0;
00486   for (PathInfo * path: m_cache_paths) {
00487     path->time_active       = 0.;
00488     path->time_premodules   = 0.;
00489     path->time_intermodules = 0.;
00490     path->time_postmodules  = 0.;
00491     path->time_total        = 0.;
00492   }
00493   for (ModuleInfo * module: m_cache_modules) {
00494     module->time_active     = 0.;
00495     module->has_just_run    = false;
00496     module->is_exclusive    = false;
00497   }
00498 }
00499 
00500 void FastTimerService::postProcessEvent(edm::Event const & event, edm::EventSetup const & setup) {
00501   //edm::LogImportant("FastTimerService") << __func__ << "(...)";
00502 
00503   if (m_enable_timing_exclusive) {
00504     for (auto & keyval: m_paths) {
00505       PathInfo & pathinfo = keyval.second;
00506       float exclusive = pathinfo.time_overhead;
00507 
00508       for (uint32_t i = 0; i <= pathinfo.last_run; ++i) {
00509         ModuleInfo * module = pathinfo.modules[i];
00510         if (module == 0)
00511           // this is a module occurring more than once in the same path, skip it after the first occurrence
00512           continue;
00513         if (module->is_exclusive)
00514           exclusive += module->time_active;
00515       }
00516       //edm::LogImportant("FastTimerService") << m_dqm_paths_exclusive_time->GetName() << "->Fill(" << pathinfo.index << ", " <<  exclusive * 1000. << ")";
00517       m_dqm_paths_exclusive_time->Fill(pathinfo.index, exclusive * 1000.);
00518       if (m_enable_dqm_bypath_exclusive) {
00519         //edm::LogImportant("FastTimerService") << pathinfo.dqm_exclusive->GetName() << "->Fill(" << exclusive * 1000. << ")";
00520         pathinfo.dqm_exclusive->Fill(exclusive * 1000.);      // convert to ms
00521       }
00522     }
00523   }
00524 
00525   // stop the per-event timer, and account event time
00526   stop(m_timer_event);
00527   m_event = delta(m_timer_event);
00528   m_summary_event += m_event;
00529   if (m_dqms) {
00530     //edm::LogImportant("FastTimerService") << m_dqm_event->GetName() << "->Fill(" << m_event * 1000. << ")";
00531     m_dqm_event->Fill(m_event * 1000.);                     // convert to ms
00532 
00533     if (m_enable_dqm_bylumi) {
00534       unsigned int lumi = event.getLuminosityBlock().luminosityBlock();
00535       //edm::LogImportant("FastTimerService") << m_dqm_bylumi_event->GetName() << "->Fill(" << lumi << ", " <<  m_event        * 1000. << ")";
00536       m_dqm_bylumi_event        ->Fill(lumi, m_event        * 1000.);       // convert to ms
00537       //edm::LogImportant("FastTimerService") << m_dqm_bylumi_source->GetName() << "->Fill(" << lumi << ", " <<  m_source       * 1000. << ")";
00538       m_dqm_bylumi_source       ->Fill(lumi, m_source       * 1000.);       // convert to ms
00539       //edm::LogImportant("FastTimerService") << m_dqm_bylumi_all_paths->GetName() << "->Fill(" << lumi << ", " <<  m_all_paths    * 1000. << ")";
00540       m_dqm_bylumi_all_paths    ->Fill(lumi, m_all_paths    * 1000.);       // convert to ms
00541       //edm::LogImportant("FastTimerService") << m_dqm_bylumi_all_endpaths->GetName() << "->Fill(" << lumi << ", " <<  m_all_endpaths * 1000. << ")";
00542       m_dqm_bylumi_all_endpaths ->Fill(lumi, m_all_endpaths * 1000.);       // convert to ms
00543     }
00544   }
00545 }
00546 
00547 void FastTimerService::preSource() {
00548   //edm::LogImportant("FastTimerService") << __func__ << "()";
00549 
00550   start(m_timer_source);
00551 
00552   // clear the event counters
00553   m_source = 0;
00554 
00555   // keep track of the total number of events
00556   ++m_summary_events;
00557 }
00558 
00559 void FastTimerService::postSource() {
00560   //edm::LogImportant("FastTimerService") << __func__ << "()";
00561 
00562   stop(m_timer_source);
00563   m_source = delta(m_timer_source);
00564   m_summary_source += m_source;
00565   if (m_dqms) {
00566     //edm::LogImportant("FastTimerService") << m_dqm_source->GetName() << "->Fill(" << m_source * 1000. << ")";
00567     m_dqm_source->Fill(m_source * 1000.);                       // convert to ms
00568   }
00569 }
00570 
00571 void FastTimerService::prePathBeginRun(std::string const & path ) {
00572   //edm::LogImportant("FastTimerService") << __func__ << "(" << path << ")";
00573 
00574   // cache the pointers to the names of the first and last path and endpath
00575   edm::service::TriggerNamesService & tns = * edm::Service<edm::service::TriggerNamesService>();
00576   if (not m_skip_first_path and not tns.getTrigPaths().empty()) {
00577     if (path == tns.getTrigPaths().front())
00578       m_first_path = & path;
00579     if (path == tns.getTrigPaths().back())
00580       m_last_path = & path;
00581   }
00582   else if (m_skip_first_path and tns.getTrigPaths().size() > 1) {
00583     if (path == tns.getTrigPaths().at(1))
00584       m_first_path = & path;
00585     if (path == tns.getTrigPaths().back())
00586       m_last_path = & path;
00587   }
00588   if (not tns.getEndPaths().empty()) {
00589     if (path == tns.getEndPaths().front())
00590       m_first_endpath = & path;
00591     if (path == tns.getEndPaths().back())
00592       m_last_endpath = & path;
00593   }
00594 }
00595 
00596 void FastTimerService::preProcessPath(std::string const & path ) {
00597   //edm::LogImportant("FastTimerService") << __func__ << "(" << path << ")";
00598 
00599   // prepare to measure the time spent between the beginning of the path and the execution of the first module
00600   m_is_first_module = true;
00601 
00602   PathMap<PathInfo>::iterator keyval = m_paths.find(path);
00603   if (keyval != m_paths.end()) {
00604     m_current_path = & keyval->second;
00605 
00606     if (m_enable_timing_modules) {
00607       // reset the status of this path's modules
00608       for (ModuleInfo * module: m_current_path->modules)
00609         if (module)
00610           module->has_just_run = false;
00611     }
00612   } else {
00613     // should never get here
00614     m_current_path = 0;
00615     edm::LogError("FastTimerService") << "FastTimerService::preProcessPath: unexpected path " << path;
00616   }
00617 
00618   // time each (end)path
00619   start(m_timer_path);
00620 
00621   if (& path == m_first_path) {
00622     // this is the first path, start the "all paths" counter
00623     m_timer_paths.first = m_timer_path.first;
00624   } else if (& path == m_first_endpath) {
00625     // this is the first endpath, start the "all paths" counter
00626     m_timer_endpaths.first = m_timer_path.first;
00627   }
00628 }
00629 
00630 void FastTimerService::postProcessPath(std::string const & path, edm::HLTPathStatus const & status) {
00631   //edm::LogImportant("FastTimerService") << __func__ << "(" << path << ", ...)";
00632 
00633   // time each (end)path
00634   stop(m_timer_path);
00635 
00636   double active = delta(m_timer_path);
00637 
00638   // if enabled, account each (end)path
00639   if (m_enable_timing_paths) {
00640 
00641     PathInfo & pathinfo = * m_current_path;
00642     pathinfo.time_active = active;
00643     pathinfo.summary_active += active;
00644 
00645     if (m_dqms) {
00646       //edm::LogImportant("FastTimerService") << m_dqm_paths_active_time->GetName() << "->Fill(" << pathinfo.index << ", " <<  active * 1000. << ")";
00647       m_dqm_paths_active_time->Fill(pathinfo.index, active * 1000.);     // convert to ms
00648       if (m_enable_dqm_bypath_active) {
00649         //edm::LogImportant("FastTimerService") << pathinfo.dqm_active->GetName() << "->Fill(" << active * 1000. << ")";
00650         pathinfo.dqm_active->Fill(active * 1000.);                      // convert to ms
00651       }
00652     }
00653 
00654     // measure the time spent between the execution of the last module and the end of the path
00655     if (m_enable_timing_modules) {
00656       double pre      = 0.;                 // time spent before the first active module
00657       double inter    = 0.;                 // time spent between active modules
00658       double post     = 0.;                 // time spent after the last active module
00659       double overhead = 0.;                 // time spent before, between, or after modules
00660       double current  = 0.;                 // time spent in modules active in the current path
00661       double total    = active;             // total per-path time, including modules already run as part of other paths
00662 
00663       // implementation note:
00664       // "active"   has already measured all the time spent in this path
00665       // "current"  will be the sum of the time spent inside each module while running this path, so that
00666       // "overhead" will be active - current
00667       // "total"    will be active + the sum of the time spent in non-active modules
00668 
00669       uint32_t last_run = status.index();     // index of the last module run in this path
00670       for (uint32_t i = 0; i <= last_run; ++i) {
00671         ModuleInfo * module = pathinfo.modules[i];
00672 
00673         // fill counter histograms - also for duplicate modules, to properly extract rejection information
00674         if (m_enable_dqm_bypath_counters) {
00675           //edm::LogImportant("FastTimerService") << pathinfo.dqm_module_counter->GetName() << "->Fill(" << i << ")";
00676           pathinfo.dqm_module_counter->Fill(i);
00677         }
00678         
00679         if (module == 0)
00680           // this is a module occurring more than once in the same path, skip it after the first occurrence
00681           continue;
00682 
00683         if (module->has_just_run) {
00684           current += module->time_active;
00685           module->is_exclusive = true;
00686         } else {
00687           total   += module->time_active;
00688           module->is_exclusive = false;
00689         }
00690 
00691         // fill detailed timing histograms
00692         if (m_enable_dqm_bypath_details) {
00693           // fill the total time for all non-duplicate modules
00694           //edm::LogImportant("FastTimerService") << pathinfo.dqm_module_total->GetName() << "->Fill(" << i << ", " <<  module->time_active * 1000. << ")";
00695           pathinfo.dqm_module_total->Fill(i, module->time_active * 1000.);      // convert to ms
00696           if (module->has_just_run) {
00697             // fill the active time only for module actually running in this path
00698             //edm::LogImportant("FastTimerService") << pathinfo.dqm_module_active->GetName() << "->Fill(" << i << ", " <<  module->time_active * 1000. << ")";
00699             pathinfo.dqm_module_active->Fill(i, module->time_active * 1000.);   // convert to ms
00700           }
00701         }
00702 
00703       }
00704 
00705       if (status.accept())
00706         if (m_enable_dqm_bypath_counters) {
00707           //edm::LogImportant("FastTimerService") << pathinfo.dqm_module_counter->GetName() << "->Fill(" << pathinfo.modules.size() << ")";
00708           pathinfo.dqm_module_counter->Fill(pathinfo.modules.size());
00709         }
00710 
00711       if (m_is_first_module) {
00712         // no modules were active during this path, account all the time as overhead
00713         pre      = 0.;
00714         inter    = 0.;
00715         post     = active;
00716         overhead = active;
00717       } else {
00718         // extract overhead information
00719         pre      = delta(m_timer_path.first,    m_timer_first_module);
00720         post     = delta(m_timer_module.second, m_timer_path.second);
00721         inter    = active - pre - current - post;
00722         // take care of numeric precision and rounding errors - the timer is less precise than nanosecond resolution
00723         if (std::abs(inter) < 1e-9)
00724           inter = 0.;
00725         overhead = active - current;
00726         // take care of numeric precision and rounding errors - the timer is less precise than nanosecond resolution
00727         if (std::abs(overhead) < 1e-9)
00728           overhead = 0.;
00729       }
00730 
00731       pathinfo.time_premodules       = pre;
00732       pathinfo.time_intermodules     = inter;
00733       pathinfo.time_postmodules      = post;
00734       pathinfo.time_overhead         = overhead;
00735       pathinfo.time_total            = total;
00736       pathinfo.summary_premodules   += pre;
00737       pathinfo.summary_intermodules += inter;
00738       pathinfo.summary_postmodules  += post;
00739       pathinfo.summary_overhead     += overhead;
00740       pathinfo.summary_total        += total;
00741       pathinfo.last_run              = last_run;
00742       if (m_dqms) {
00743         if (m_enable_dqm_bypath_overhead) {
00744           //edm::LogImportant("FastTimerService") << pathinfo.dqm_overhead->GetName() << "->Fill(" << overhead * 1000. << ")";
00745           pathinfo.dqm_premodules  ->Fill(pre      * 1000.);      // convert to ms
00746           pathinfo.dqm_intermodules->Fill(inter    * 1000.);      // convert to ms
00747           pathinfo.dqm_postmodules ->Fill(post     * 1000.);      // convert to ms
00748           pathinfo.dqm_overhead    ->Fill(overhead * 1000.);      // convert to ms
00749         }
00750         //edm::LogImportant("FastTimerService") << m_dqm_paths_total_time->GetName() << "->Fill(" << pathinfo.index << ", " <<  total * 1000. << ")";
00751         m_dqm_paths_total_time->Fill(pathinfo.index, total * 1000.);
00752         if (m_enable_dqm_bypath_total) {
00753           //edm::LogImportant("FastTimerService") << pathinfo.dqm_total->GetName() << "->Fill(" << total    * 1000. << ")";
00754           pathinfo.dqm_total       ->Fill(total    * 1000.);      // convert to ms
00755         }
00756       }
00757     }
00758   }
00759 
00760   if (& path == m_last_path) {
00761     // this is the last path, stop and account the "all paths" counter
00762     m_timer_paths.second = m_timer_path.second;
00763     m_all_paths = delta(m_timer_paths);
00764     m_summary_all_paths += m_all_paths;
00765     if (m_dqms) {
00766       //edm::LogImportant("FastTimerService") << m_dqm_all_paths->GetName() << "->Fill(" << m_all_paths * 1000. << ")";
00767       m_dqm_all_paths->Fill(m_all_paths * 1000.);               // convert to ms
00768     }
00769   } else if (& path == m_last_endpath) {
00770     // this is the last endpath, stop and account the "all endpaths" counter
00771     m_timer_endpaths.second = m_timer_path.second;
00772     m_all_endpaths = delta(m_timer_endpaths);
00773     m_summary_all_endpaths += m_all_endpaths;
00774     if (m_dqms) {
00775       //edm::LogImportant("FastTimerService") << m_dqm_all_endpaths->GetName() << "->Fill(" << m_all_endpaths * 1000. << ")";
00776       m_dqm_all_endpaths->Fill(m_all_endpaths * 1000.);         // convert to ms
00777     }
00778   }
00779 
00780 }
00781 
00782 void FastTimerService::preModule(edm::ModuleDescription const & module) {
00783   //edm::LogImportant("FastTimerService") << __func__ << "(" << & module << ")";
00784 
00785   // this is ever called only if m_enable_timing_modules = true
00786   assert(m_enable_timing_modules);
00787 
00788   // time each module
00789   start(m_timer_module);
00790 
00791   if (m_is_first_module) {
00792     m_is_first_module = false;
00793 
00794     // measure the time spent between the beginning of the path and the execution of the first module
00795     m_timer_first_module = m_timer_module.first;
00796   } 
00797 }
00798 
00799 void FastTimerService::postModule(edm::ModuleDescription const & module) {
00800   //edm::LogImportant("FastTimerService") << __func__ << "(" << & module << ")";
00801 
00802   // this is ever called only if m_enable_timing_modules = true
00803   assert(m_enable_timing_modules);
00804 
00805   // time and account each module
00806   stop(m_timer_module);
00807 
00808   ModuleMap<ModuleInfo>::iterator keyval = m_modules.find(& module);
00809   if (keyval != m_modules.end()) {
00810     double time = delta(m_timer_module);
00811     ModuleInfo & module = keyval->second;
00812     module.has_just_run    = true;
00813     module.time_active     = time;
00814     module.summary_active += time;
00815 
00816     if (m_dqms and m_enable_dqm_bymodule) {
00817       //edm::LogImportant("FastTimerService") << module.dqm_active->GetName() << "->Fill(" << time * 1000. << ")";
00818       module.dqm_active->Fill(time * 1000.);                    // convert to ms
00819     }
00820   } else {
00821     // should never get here
00822     edm::LogError("FastTimerService") << "FastTimerService::postModule: unexpected module " << module.moduleLabel();
00823   }
00824 }
00825 
00826 // find the module description associated to a module, by label
00827 edm::ModuleDescription const * FastTimerService::findModuleDescription(const std::string & label) const {
00828   // no descriptions are associated to an empty label
00829   if (label.empty())
00830     return 0;
00831 
00832   // fix the name of negated or ignored modules
00833   std::string const & target = (label[0] == '!' or label[0] == '-') ? label.substr(1) : label;
00834 
00835   for (auto const & keyval: m_modules) {
00836     if (keyval.first == 0) {
00837       // this should never happen, but it would cause a segmentation fault to insert a null pointer in the path map, se we explicitly check for it and skip it
00838       edm::LogError("FastTimerService") << "FastTimerService::findModuleDescription: invalid entry detected in ModuleMap<ModuleInfo> m_modules, skipping";
00839       continue;
00840     }
00841     if (keyval.first->moduleLabel() == target) {
00842       return keyval.first;
00843     }
00844   }
00845   // not found
00846   return 0;
00847 }
00848 
00849 // associate to a path all the modules it contains
00850 void FastTimerService::fillPathMap(std::string const & name, std::vector<std::string> const & modules) {
00851   std::vector<ModuleInfo *> & pathmap = m_paths[name].modules;
00852   pathmap.reserve( modules.size() );
00853   std::tr1::unordered_set<edm::ModuleDescription const *> pool;        // keep track of inserted modules
00854   for (auto const & module: modules) {
00855     edm::ModuleDescription const * md = findModuleDescription(module);
00856     if (md == 0) {
00857       // no matching module was found
00858       pathmap.push_back( 0 );
00859     } else if (pool.insert(md).second) {
00860       // new module
00861       pathmap.push_back( & m_modules[md] );
00862     } else {
00863       // duplicate module
00864       pathmap.push_back( 0 );
00865     }
00866   }
00867 }
00868 
00869 
00870 // query the current module/path/event
00871 // Note: these functions incur in a "per-call timer overhead" (see above), currently of the order of 340ns
00872 
00873 // return the time spent since the last preModule() event
00874 double FastTimerService::currentModuleTime() const {
00875   struct timespec now;
00876   gettime(now);
00877   return delta(m_timer_module.first, now);
00878 }
00879 
00880 // return the time spent since the last preProcessPath() event
00881 double FastTimerService::currentPathTime() const {
00882   struct timespec now;
00883   gettime(now);
00884   return delta(m_timer_path.first, now);
00885 }
00886 
00887 // return the time spent since the last preProcessEvent() event
00888 double FastTimerService::currentEventTime() const {
00889   struct timespec now;
00890   gettime(now);
00891   return delta(m_timer_event.first, now);
00892 }
00893 
00894 // query the time spent in a module (available after the module has run)
00895 double FastTimerService::queryModuleTime(const edm::ModuleDescription & module) const {
00896   ModuleMap<ModuleInfo>::const_iterator keyval = m_modules.find(& module);
00897   if (keyval != m_modules.end()) {
00898     return keyval->second.time_active;
00899   } else {
00900     edm::LogError("FastTimerService") << "FastTimerService::postModule: unexpected module " << module.moduleLabel();
00901     return 0.;
00902   }
00903 }
00904 
00905 // query the time spent in a path (available after the path has run)
00906 double FastTimerService::queryPathActiveTime(const std::string & path) const {
00907   PathMap<PathInfo>::const_iterator keyval = m_paths.find(path);
00908   if (keyval != m_paths.end()) {
00909     return keyval->second.time_active;
00910   } else {
00911     edm::LogError("FastTimerService") << "FastTimerService::postModule: unexpected path " << path;
00912     return 0.;
00913   }
00914 }
00915 
00916 // query the total time spent in a path (available after the path has run)
00917 double FastTimerService::queryPathTotalTime(const std::string & path) const {
00918   PathMap<PathInfo>::const_iterator keyval = m_paths.find(path);
00919   if (keyval != m_paths.end()) {
00920     return keyval->second.time_total;
00921   } else {
00922     edm::LogError("FastTimerService") << "FastTimerService::postModule: unexpected path " << path;
00923     return 0.;
00924   }
00925 }
00926 
00927 // query the time spent in the current event's source (available during event processing)
00928 double FastTimerService::querySourceTime() const {
00929   return m_source;
00930 }
00931 
00932 // query the time spent in the current event's paths (available during endpaths)
00933 double FastTimerService::queryPathsTime() const {
00934   return m_all_paths;
00935 }
00936 
00937 // query the time spent in the current event's endpaths (available after all endpaths have run)
00938 double FastTimerService::queryEndPathsTime() const {
00939   return m_all_endpaths;
00940 }
00941 
00942 // query the time spent processing the current event (available after the event has been processed)
00943 double FastTimerService::queryEventTime() const {
00944   return m_event;
00945 }
00946 
00947 // describe the module's configuration
00948 void FastTimerService::fillDescriptions(edm::ConfigurationDescriptions & descriptions) {
00949   edm::ParameterSetDescription desc;
00950   desc.addUntracked<bool>(   "useRealTimeClock",         true);
00951   desc.addUntracked<bool>(   "enableTimingPaths",        true);
00952   desc.addUntracked<bool>(   "enableTimingModules",      true);
00953   desc.addUntracked<bool>(   "enableTimingExclusive",    false);
00954   desc.addUntracked<bool>(   "enableTimingSummary",      false);
00955   desc.addUntracked<bool>(   "skipFirstPath",            false), 
00956   desc.addUntracked<bool>(   "enableDQM",                true);
00957   desc.addUntracked<bool>(   "enableDQMbyPathActive",    false);
00958   desc.addUntracked<bool>(   "enableDQMbyPathTotal",     true);
00959   desc.addUntracked<bool>(   "enableDQMbyPathOverhead",  false);
00960   desc.addUntracked<bool>(   "enableDQMbyPathDetails",   false);
00961   desc.addUntracked<bool>(   "enableDQMbyPathCounters",  true);
00962   desc.addUntracked<bool>(   "enableDQMbyPathExclusive", false);
00963   desc.addUntracked<bool>(   "enableDQMbyModule",        false);
00964   desc.addUntracked<bool>(   "enableDQMbyLumi",          false);
00965   desc.addUntracked<double>( "dqmTimeRange",             1000. );   // ms
00966   desc.addUntracked<double>( "dqmTimeResolution",           5. );   // ms
00967   desc.addUntracked<double>( "dqmPathTimeRange",          100. );   // ms
00968   desc.addUntracked<double>( "dqmPathTimeResolution",       0.5);   // ms
00969   desc.addUntracked<double>( "dqmModuleTimeRange",         40. );   // ms
00970   desc.addUntracked<double>( "dqmModuleTimeResolution",     0.2);   // ms
00971   desc.addUntracked<uint32_t>( "dqmLumiSectionsRange",    2500 );    // ~ 16 hours
00972   desc.addUntracked<std::string>( "dqmPath",             "HLT/TimerService");
00973   descriptions.add("FastTimerService", desc);
00974 }