14 #include "boost/format.hpp" 18 #include "cetlib/HorizontalRule.h" 19 #include "cetlib/sqlite/Connection.h" 20 #include "cetlib/sqlite/Ntuple.h" 21 #include "cetlib/sqlite/helpers.h" 22 #include "cetlib/sqlite/statistics.h" 36 using std::chrono::steady_clock;
43 auto now = std::bind(&steady_clock::now);
47 explicit Statistics() =
default;
49 explicit Statistics(
string const& p,
61 , median{sqlite::median(db, table, column)}
62 , rms{sqlite::rms(db, table, column)}
63 ,
n{sqlite::nrows(db, table)}
78 operator<<(std::ostream& os, Statistics
const& info)
80 string label{info.path};
81 if (!info.mod_label.empty()) {
82 label +=
':' + info.mod_label;
84 if (!info.mod_type.empty()) {
85 label +=
':' + info.mod_type;
87 os <<
label <<
" " << boost::format(
" %=12g ") % info.min
88 << boost::format(
" %=12g ") % info.mean
89 << boost::format(
" %=12g ") % info.max
90 << boost::format(
" %=12g ") % info.median
91 << boost::format(
" %=12g ") % info.rms
92 << boost::format(
" %=10d ") % info.n;
118 void prePathProcessing(
string const&);
122 void preEventReading();
123 void postEventReading(
Event const&);
125 void preEventProcessing(
Event const&);
126 void postEventProcessing(
Event const&);
131 void logToDatabase_(Statistics
const& evt,
132 std::vector<Statistics>
const& modules);
133 void logToDestination_(Statistics
const& evt,
134 std::vector<Statistics>
const& modules);
146 cet::sqlite::Connection
db_;
148 string sourceType_{};
150 template <
unsigned SIZE>
157 cet::sqlite::Ntuple<uint32_t, uint32_t, uint32_t, string, double>;
158 using timeEvent_t = cet::sqlite::Ntuple<uint32_t, uint32_t, uint32_t, double>;
160 Ntuple<uint32_t, uint32_t, uint32_t, string, string, string, double>;
172 : printSummary_{config().printSummary()}
174 config().dbOutput().filename())}
190 unsigned const nSchedules{1u};
191 data_.resize(nSchedules);
193 iRegistry.sPostSourceConstruction.watch(
this,
208 iRegistry.sPostModule.watch(
209 [
this](
auto const& md) { this->
recordTime(md,
""s); });
211 iRegistry.sPostWriteEvent.watch(
212 [
this](
auto const& md) { this->
recordTime(md,
"(write)"s); });
221 data_[sid].pathName = pathname;
236 query_result<std::size_t> rEvents;
239 query_result<std::size_t> rModules;
242 auto const nEventRows = unique_value(rEvents);
243 auto const nModuleRows = unique_value(rModules);
245 if (nEventRows == 0 && nModuleRows == 0) {
250 if (nEventRows == 0 && nModuleRows != 0) {
251 std::string
const errMsg{
252 "Malformed TimeTracker database. The TimeEvent table is empty, but\n" 253 "the TimeModule table is not. This can happen if an exception has\n" 254 "been thrown from a module while processing the first event. Any saved\n" 255 "database file is suspect and should not be used."};
266 string const fullEventTime_ddl =
267 "CREATE TABLE temp.fullEventTime AS " 268 "SELECT Run,Subrun,Event,SUM(Time) AS FullEventTime FROM (" 269 " SELECT Run,Subrun,Event,Time FROM TimeEvent" 271 " SELECT Run,Subrun,Event,Time FROM TimeModule WHERE ModuleType LIKE " 274 " SELECT Run,Subrun,Event,Time FROM TimeSource" 275 ") GROUP BY Run,Subrun,Event";
278 exec(
db_, fullEventTime_ddl);
279 Statistics
const evtStats{
280 "Full event",
"",
"",
db_,
"temp.fullEventTime",
"FullEventTime"};
281 drop_table(
db_,
"temp.fullEventTime");
283 query_result<string, string, string> r;
284 r << select_distinct(
"Path",
"ModuleLabel",
"ModuleType")
287 std::vector<Statistics> modStats;
288 modStats.emplace_back(
291 for (
auto const& row : r) {
292 string path, mod_label, mod_type;
293 tie(path, mod_label, mod_type) = row;
294 create_table_as(
"temp.tmpModTable",
296 .from(
db_,
"TimeModule")
297 .where(
"Path='"s + path +
"'"s +
" AND ModuleLabel='"s +
298 mod_label +
"'"s +
" AND ModuleType='"s +
300 modStats.emplace_back(
301 path, mod_label, mod_type,
db_,
"temp.tmpModTable",
"Time");
302 drop_table(
db_,
"temp.tmpModTable");
323 d.eventStart = now();
333 auto const t = std::chrono::duration<double>{now() -
d.eventStart}.count();
335 d.eventID.run(),
d.eventID.subRun(),
d.eventID.event(),
sourceType_, t);
345 assert(
d.eventID ==
e.id());
346 d.eventStart = now();
354 auto const&
d =
data_[sid];
355 auto const t = std::chrono::duration<double>{now() -
d.eventStart}.count();
357 d.eventID.run(),
d.eventID.subRun(),
d.eventID.event(), t);
367 d.moduleStart = now();
372 string const& suffix)
376 auto const&
d =
data_[sid];
377 auto const t = std::chrono::duration<double>{now() -
d.moduleStart}.count();
390 std::vector<Statistics>
const& modules)
392 std::size_t width{30};
393 auto identifier_size = [](Statistics
const&
s) {
394 return s.path.size() +
s.mod_label.size() +
s.mod_type.size() +
397 cet::for_all(modules, [&identifier_size, &width](
auto const& mod) {
398 width =
std::max(width, identifier_size(mod));
401 std::ostringstream msgOss;
402 HorizontalRule
const rule{width + 4 + 5 * 14 + 12};
405 << std::setw(width + 2) <<
std::left <<
"TimeTracker printout (sec)" 406 << boost::format(
" %=12s ") %
"Min" << boost::format(
" %=12s ") %
"Avg" 407 << boost::format(
" %=12s ") %
"Max" 408 << boost::format(
" %=12s ") %
"Median" 409 << boost::format(
" %=12s ") %
"RMS" 410 << boost::format(
" %=10s ") %
"nEvts" 413 msgOss << rule(
'=') <<
'\n';
416 msgOss <<
"[ No processed events ]\n";
420 msgOss << setw(width) << evt <<
'\n' << rule(
'-') <<
'\n';
421 for (
auto const& mod : modules) {
422 msgOss << setw(width) << mod <<
'\n';
timeEvent_t timeEventTable_
static constexpr EventID invalidEvent()
name_array< 5u > timeSourceTuple_
void startTime(ModuleDescription const &)
TimeTracker(ServiceTable< Config > const &, ActivityRegistry &)
void logToDestination_(Statistics const &evt, std::vector< Statistics > const &modules)
cet::sqlite::Ntuple< uint32_t, uint32_t, uint32_t, string, double > timeSource_t
std::vector< PerScheduleData > data_
#define DEFINE_ART_SERVICE(svc)
void prePathProcessing(string const &)
constexpr id_type id() const
static ScheduleID first()
#define DECLARE_ART_SERVICE(svc, scope)
cet::sqlite::Ntuple< uint32_t, uint32_t, uint32_t, double > timeEvent_t
Stream & operator<<(Stream &&out, CallInfo_t const &info)
Helper operator to insert a call information in a stream with default options.
void postSourceConstruction(ModuleDescription const &)
name_array< 4u > timeEventTuple_
name_array< 7u > timeModuleTuple_
cet::sqlite::name_array< SIZE > name_array
timeModule_t timeModuleTable_
std::string const & moduleName() const
cet::sqlite::Connection db_
timeSource_t timeSourceTable_
steady_clock::time_point moduleStart
std::string const & moduleLabel() const
void recordTime(ModuleDescription const &md, string const &suffix)
constexpr auto const & left(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
double mean(const std::vector< short > &wf, size_t start, size_t nsample)
void postEventReading(Event const &)
steady_clock::time_point eventStart
void postEventProcessing(Event const &)
void preEventProcessing(Event const &)
MaybeLogger_< ELseverityLevel::ELsev_severe, true > LogAbsolute
cet::sqlite::Ntuple< uint32_t, uint32_t, uint32_t, string, string, string, double > timeModule_t