19 #error "This source file can be built only for Linux platforms." 23 #include "art/Framework/Services/Optional/detail/LinuxMallInfo.h" 34 #include "art/Utilities/LinuxProcData.h" 35 #include "art/Utilities/LinuxProcMgr.h" 38 #include "cetlib/HorizontalRule.h" 39 #include "cetlib/container_algorithms.h" 40 #include "cetlib/sqlite/Connection.h" 41 #include "cetlib/sqlite/Ntuple.h" 42 #include "cetlib/sqlite/select.h" 56 using namespace string_literals;
59 using art::detail::LinuxMallInfo;
68 using peakUsage_t = cet::sqlite::Ntuple<string, double, string>;
70 cet::sqlite::Ntuple<string, string, string, double, double>;
72 cet::sqlite::Ntuple<string, uint32_t, uint32_t, uint32_t, double, double>;
109 static constexpr
bool service_handle_allowed{
false};
112 template <
typename T>
116 template <
typename T>
132 void recordOtherData(
ModuleContext const& mc,
string const& step);
133 void recordEventData(
Event const&
e,
string const& step);
134 void recordModuleData(
ModuleContext const& mc,
string const& step);
136 bool checkMallocConfig_(
string const&,
bool);
137 void recordPeakUsages_();
139 bool using_file_database_()
const;
141 bool anyTableFull_()
const;
143 LinuxProcMgr procInfo_{};
145 unique_ptr<cet::sqlite::Connection>
const db_;
152 EventID currentEventID_{EventID::invalidEvent()};
155 {
"Step",
"ModuleLabel",
"ModuleType",
"Vsize",
"RSS"}};
157 {
"Step",
"Run",
"SubRun",
"Event",
"Vsize",
"RSS"}};
202 : fileName_{config().dbOutput().filename()}
206 config().includeMallocInfo())}
214 make_unique<memEventHeap_t>(*
db_,
219 make_unique<memModuleHeap_t>(*
db_,
228 <<
"Since " << nthreads
229 <<
" threads have been configured, only process-level\n" 230 "memory usage will be recorded at the end of the job.";
233 if (!
fileName_.empty() && nthreads == 1u) {
234 iReg.sPreModuleConstruction.watch([
this](
auto const& md) {
237 iReg.sPostModuleConstruction.watch([
this](
auto const& md) {
240 iReg.sPreModuleBeginJob.watch(
242 iReg.sPostModuleBeginJob.watch(
243 [
this](
auto const& md) { this->
recordOtherData(md,
"PostBeginJob"); });
244 iReg.sPreModuleBeginRun.watch(
246 iReg.sPostModuleBeginRun.watch(
247 [
this](
auto const& mc) { this->
recordOtherData(mc,
"PostBeginRun"); });
248 iReg.sPreModuleBeginSubRun.watch([
this](
auto const& mc) {
251 iReg.sPostModuleBeginSubRun.watch([
this](
auto const& mc) {
260 iReg.sPreModule.watch([
this](
auto const& mc) {
263 iReg.sPostModule.watch([
this](
auto const& mc) {
266 iReg.sPreWriteEvent.watch([
this](
auto const& mc) {
269 iReg.sPostWriteEvent.watch([
this](
auto const& mc) {
272 iReg.sPreModuleEndSubRun.watch(
273 [
this](
auto const& mc) { this->
recordOtherData(mc,
"PreEndSubRun"); });
274 iReg.sPreModuleEndRun.watch(
276 iReg.sPreModuleEndJob.watch(
278 iReg.sPostModuleEndSubRun.watch(
279 [
this](
auto const& mc) { this->
recordOtherData(mc,
"PostEndSubRun"); });
280 iReg.sPostModuleEndRun.watch(
282 iReg.sPostModuleEndJob.watch(
297 auto const data =
procInfo_.getCurrentData();
301 LinuxProcData::getValueInMB<vsize_t>(data),
302 LinuxProcData::getValueInMB<rss_t>(data));
309 auto const currentMemory =
procInfo_.getCurrentData();
314 LinuxProcData::getValueInMB<vsize_t>(currentMemory),
315 LinuxProcData::getValueInMB<rss_t>(currentMemory));
317 auto minfo = LinuxMallInfo{}.get();
335 auto const currentMemory =
procInfo_.getCurrentData();
343 LinuxProcData::getValueInMB<vsize_t>(currentMemory),
344 LinuxProcData::getValueInMB<rss_t>(currentMemory));
346 auto minfo = LinuxMallInfo{}.get();
376 if (include && dbfilename.empty()) {
377 string const errmsg =
378 "\n'includeMallocInfo : true' is valid only if a nonempty db filename is specified:\n\n"s +
379 " MemoryTracker: {\n" 380 " includeMallocInfo: true\n" 382 " filename: \"your_filename.db\"\n" 394 "VmPeak",
procInfo_.getVmPeak(),
"Peak virtual memory (MB)");
396 "VmHWM",
procInfo_.getVmHWM(),
"Peak resident set size (MB)");
425 query_result<double> rVMax;
426 query_result<double> rRMax;
427 rVMax << select(
"Value")
429 .where(
"Name='VmPeak'");
430 rRMax << select(
"Value")
432 .where(
"Name='VmHWM'");
434 HorizontalRule
const rule{100};
435 log <<
'\n' << rule(
'=') <<
'\n';
438 log <<
"The SQLite database connected to the MemoryTracker exceeded the " 439 "available resources.\n";
440 log <<
"No memory usage summary is available.\n";
442 <<
" will contain an incomplete record of this job's memory usage.\n";
444 log <<
std::left <<
"MemoryTracker summary (base-10 MB units used)\n\n";
445 log <<
" Peak virtual memory usage (VmPeak) : " << unique_value(rVMax)
447 <<
" Peak resident set size usage (VmHWM): " << unique_value(rRMax)
450 log <<
" Details saved in: '" <<
fileName_ <<
"'\n";
name_array< 11u > eventHeapColumns_
bool const includeMallocInfo_
auto const & pathName() const
art::LinuxProcData::rss_t rss_t
std::string const & moduleLabel() const
name_array< 9u > moduleColumns_
cet::sqlite::name_array< N > name_array
peakUsage_t peakUsageTable_
unique_ptr< memEventHeap_t > eventHeapTable_
ScheduleID::size_type nthreads() const
cet::sqlite::Ntuple< string, uint32_t, uint32_t, uint32_t, int, int, int, int, int, int, int > memEventHeap_t
bool using_file_database_() const
void recordEventData(Event const &e, string const &step)
std::string const & moduleName() const
auto const & moduleName() const
bool anyTableFull_() const
#define DECLARE_ART_SERVICE(svc, scope)
unique_ptr< cet::sqlite::Connection > const db_
cet::sqlite::Ntuple< string, string, string, double, double > otherInfo_t
cet::sqlite::Ntuple< string, uint32_t, uint32_t, uint32_t, string, string, string, double, double > memModule_t
name_array< 3u > peakUsageColumns_
bool checkMallocConfig_(string const &, bool)
name_array< 5u > otherInfoColumns_
cet::sqlite::Ntuple< string, uint32_t, uint32_t, uint32_t, string, string, string, int, int, int, int, int, int, int > memModuleHeap_t
name_array< 6u > eventColumns_
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
cet::sqlite::Ntuple< string, double, string > peakUsage_t
#define DEFINE_ART_SERVICE(svc)
constexpr auto const & left(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
art::LinuxProcData::vsize_t vsize_t
auto const & moduleDescription() const
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
auto const & moduleLabel() const
EventNumber_t event() const
name_array< 14u > moduleHeapColumns_
void recordModuleData(ModuleContext const &mc, string const &step)
static Globals * instance()
bool const overwriteContents_
void recordOtherData(ModuleDescription const &md, string const &step)
otherInfo_t otherInfoTable_
unique_ptr< memModuleHeap_t > moduleHeapTable_
SubRunNumber_t subRun() const
cet::sqlite::Ntuple< string, uint32_t, uint32_t, uint32_t, double, double > memEvent_t