14 #include "patchlevel.h"
18 #define Py_False ( (PyObject*)(void*)&_Py_ZeroStruct )
23 #define Py_True ( (PyObject*)(void*)&_Py_TrueStruct )
30 #include <sys/times.h>
38 #include "Gaudi/Property.h"
39 #include "GaudiKernel/IIncidentSvc.h"
40 #include "GaudiKernel/Incident.h"
41 #include "GaudiKernel/IChronoStatSvc.h"
42 #include "GaudiKernel/GaudiException.h"
43 #include "GaudiKernel/IAlgManager.h"
44 #include "GaudiKernel/ServiceHandle.h"
46 #include "GaudiKernel/IIoComponentMgr.h"
55 #include "AIDA/IBaseHistogram.h"
68 #include "CPyCppyy/PyException.h"
71 #define PMON_COMP_FMT \
77 "%8.3f %8.3f %8.3f %8.3f " \
79 "%8.3f %8.3f %8.3f %lu %lu\n"
81 #define PMON_IOCOMP_FMT \
85 "%8.3f %8.3f %8.3f %8.3f " \
87 "%8.3f %8.3f %8.3f %8.3f " \
89 "%8.3f %8.3f %8.3f %8.3f\n"
98 #define PMON_MSG_LVL_NOCHK(lvl, lvlname, x) \
99 std::cout << "PerfMonSvc: " << lvlname " " << x << "\n"
101 #define PMON_MSG_LVL(lvl, lvlname, x) \
103 if (this->msgLvl (lvl)) { \
104 PMON_MSG_LVL_NOCHK(lvl, lvlname, x); \
108 #define PMON_VERBOSE(x) PMON_MSG_LVL(MSG::VERBOSE, "VERBOSE", x)
109 #define PMON_DEBUG(x) PMON_MSG_LVL(MSG::DEBUG, " DEBUG", x)
110 #define PMON_INFO(x) PMON_MSG_LVL_NOCHK(MSG::INFO, " INFO", x)
111 #define PMON_WARNING(x) PMON_MSG_LVL_NOCHK(MSG::WARNING, "WARNING", x)
112 #define PMON_ERROR(x) PMON_MSG_LVL_NOCHK(MSG::ERROR, " ERROR", x)
113 #define PMON_FATAL(x) PMON_MSG_LVL_NOCHK(MSG::FATAL, " FATAL", x)
114 #define PMON_ALWAYS(x) PMON_MSG_LVL_NOCHK(MSG::ALWAYS, " ALWAYS", x)
123 PyObject* pytype = 0, *pyvalue = 0, *pytrace = 0;
124 PyErr_Fetch (&pytype, &pyvalue, &pytrace);
126 Py_XINCREF (pyvalue);
127 Py_XINCREF (pytrace);
129 PyErr_Restore (pytype, pyvalue, pytrace);
137 my_basename(
const std::string&
path)
139 char *pathc = strdup(
path.c_str());
141 std::string o(bname);
147 my_dirname(
const std::string&
path)
149 char *pathc = strdup(
path.c_str());
151 std::string o(
dname);
158 static const int kb = 1024;
159 static const int Mb = 1024 * 1024;
179 m_chrono (
"ChronoStatSvc/ChronoStatSvc",
name ),
199 "Maximum allowed variation of virtual memory (in bytes) "
200 "between last print-out and current vmem value, before "
201 "triggering a new print-out" );
205 "Name of the output file to hold performance data" );
209 "List of algorithms to be profiled. If empty list "
210 "(default), all the algorithms known to the ApplicationMgr "
217 "List of <CppType>#<SgKey> containers for which one wants "
218 "to gather I/O data" );
224 "switch to enable or not the on-the-fly double-counting "
229 "monitoring level for monitoring granularity.\n" \
236 "name of the shelve file containing jobo metadata (domain "\
237 "flags, components' list, ...)");
241 "Whether or not to enable semi-detailed monitoring.\n" \
244 " 2: Enabled with full output in logfile");
248 "Needed internally to time configuration step. Do not modify this property." );
252 "Trigger print of perf metrics before and after each auditing." );
283 auto cwd = std::filesystem::current_path();
292 stopAud(
"fin",
"PerfMonSlice" );
304 std::string pmonsd_out(
m_outFileName);pmonsd_out+=
".pmon.pmonsd.txt";
305 std::string pmon_tarball(
m_outFileName);pmon_tarball+=
".pmon.gz";
312 for (StatStore_t::const_iterator
320 const_cast<char*
>(
"_set_stats"),
321 const_cast<char*
>(
"sIffffffffffffffffIfffififif"),
322 (
char*)istat->first.c_str(),
323 stats.cpu.nEntries(),
324 stats.cpu.flagMean(),
325 stats.cpu.flagMeanErr(),
326 stats.cpu_user.flagMean(),
327 stats.cpu_user.flagMeanErr(),
328 stats.cpu_sys.flagMean(),
329 stats.cpu_sys.flagMeanErr(),
330 stats.real.flagMean(),
331 stats.real.flagMeanErr(),
332 stats.vmem.flagMean(),
333 stats.vmem.flagMeanErr(),
334 stats.malloc.flagMean(),
335 stats.malloc.flagMeanErr(),
336 stats.nalloc.flagMean(),
337 stats.nalloc.flagMeanErr(),
339 stats.rt.flagMeanErr(),
352 PMON_WARNING(
"Problem on python side during finalize() !!");
362 const_cast<char*
>(
"finalize"),
363 const_cast<char*
>(
"") );
365 PMON_WARNING(
"Problem on python side during finalize() !!");
376 std::filesystem::current_path(
cwd);
392 if (!iomgr.retrieve().isSuccess()) {
394 return StatusCode::FAILURE;
397 if (!iomgr->io_hasitem(
this)) {
398 ATH_MSG_ERROR(
"IoComponentMgr does not know about myself !");
399 return StatusCode::FAILURE;
402 std::string stream_name =
m_outFileName.value()+
".pmon.stream";
403 std::string orig_stream_name = stream_name;
405 if (!iomgr->io_contains(
this, stream_name)) {
406 ATH_MSG_ERROR(
"IoComponentMgr does not know about [" << stream_name <<
"] !");
407 return StatusCode::FAILURE;
409 if (!iomgr->io_retrieve(
this, stream_name).isSuccess()) {
410 ATH_MSG_ERROR(
"Could not retrieve new value for [" << stream_name <<
"] !");
411 return StatusCode::FAILURE;
413 if (stream_name.empty()) {
414 ATH_MSG_DEBUG(
"io_reinit called in parent process. No actions required.");
415 return StatusCode::SUCCESS;
423 stream_name =
m_workerDir +
"/" + my_basename(orig_stream_name);
428 int old_stream =
open(orig_stream_name.c_str(), O_RDONLY);
429 if (old_stream < 0) {
431 << orig_stream_name <<
"] !");
432 return StatusCode::FAILURE;
436 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
439 strerror_r(errno, errbuf,
sizeof(errbuf));
443 return StatusCode::FAILURE;
449 while((bytes =
read(old_stream,
line,
sizeof(
line))) > 0)
453 int close_sc = close(old_stream);
455 ATH_MSG_INFO(
"could not close the re-open old pmon.stream file");
457 ATH_MSG_INFO(
"reopening [" << stream_name <<
"]... [ok]");
458 return StatusCode::SUCCESS;
475 strerror_r(errno, errbuf,
sizeof(errbuf));
478 return StatusCode::FAILURE;
481 return StatusCode::SUCCESS;
497 const std::string stream_name =
m_outFileName.value()+
".pmon.stream";
499 PMON_INFO(
"opening pmon-stream file [" << stream_name <<
"]...");
502 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
505 PMON_ERROR(
"could not open pmon-stream file ["
506 << stream_name <<
"] !");
507 return StatusCode::FAILURE;
511 const char* hdr =
"#data format: comp-id idx cpu-fields(4) mem-fields(4)\n";
518 for (std::size_t istep=0,
imax=PerfMon::Steps.
size();
521 const std::string&
step = PerfMon::Steps[istep];
526 const std::string
step =
"io";
531 const std::string
step =
"usr";
537 PMON_INFO(
"Retrieving PyPerfMonSvc object...");
538 const std::string moduleName =
"PerfMonComps.PyPerfMon";
539 PyObject*
module = PyImport_ImportModule(
const_cast<char*
>(moduleName.c_str()) );
541 PMON_ERROR(
"Could not import [" << moduleName <<
"] !!");
546 PMON_INFO(
"Retrieving PyPerfMonSvc object...");
548 const std::string fctName =
"retrieve_pmon_svc";
550 py_fct = PyDict_GetItemString(PyModule_GetDict(
module),
551 const_cast<char*
>(fctName.c_str()));
553 PMON_ERROR(
"could not retrieve function [" << fctName <<
"] from "
554 "module [" << moduleName <<
"] !!");
557 const std::string pickle_name =
m_outFileName.value()+
".props.pkl";
558 m_pySvc = PyObject_CallFunction(py_fct,
560 (
char*)pickle_name.c_str());
562 PMON_ERROR(
"problem calling function [" << fctName <<
"] from "
563 "module [" << moduleName <<
"] !!");
566 PMON_INFO(
"Retrieving PyPerfMonSvc object... [OK]");
574 const_cast<char*
>(
"initialize"),
575 const_cast<char*
>(
"") );
577 PMON_WARNING(
"Problem on python side during initialize() !!");
589 std::ostringstream
out;
593 std::ostream_iterator<std::string>(
out,
" " ) );
601 std::ostringstream
out;
605 std::ostream_iterator<std::string>(
out,
" " ) );
612 if ( !incSvc.retrieve().isSuccess() ) {
614 return StatusCode::FAILURE;
616 incSvc->addListener(
this, IncidentType::SvcPostFinalize );
621 msg() ).isSuccess() ) {
622 PMON_ERROR(
"Could not register auditor [Athena::PerfMonAuditor] !!");
623 return StatusCode::FAILURE;
630 if ( !iomgr.retrieve().isSuccess() ) {
631 ATH_MSG_ERROR (
"could not retrieve I/O component manager !");
632 return StatusCode::FAILURE;
634 if ( !iomgr->io_register(
this).isSuccess() ) {
635 ATH_MSG_ERROR (
"could not register with the I/O component manager !");
636 return StatusCode::FAILURE;
640 if ( !iomgr->io_register(
this,
642 stream_name).isSuccess() ) {
644 << stream_name <<
"] with the I/O component manager...");
645 return StatusCode::FAILURE;
653 const_cast<char*
>(
"install_pmon_dso_logger"),
654 const_cast<char*
>(
""),
655 const_cast<char*
>(
""));
657 PMON_WARNING(
"Problem during pmon-dso-logger installation");
660 #if PY_MAJOR_VERSION < 3
661 long do_dso = PyInt_AS_LONG(
res);
663 long do_dso = PyLong_AS_LONG(
res);
677 return StatusCode::SUCCESS;
687 return StatusCode::SUCCESS;
702 return Service::queryInterface(riid, ppvInterface);
705 return StatusCode::SUCCESS;
713 std::vector<std::string>
716 CompTuple_t::const_iterator itr =
m_ntuple.
comp.find(stepName);
718 return std::vector<std::string>();
723 std::vector<std::string> comps;
724 comps.reserve(
store.size());
725 for (CompStore_t::const_iterator
730 comps.push_back(jtr->first);
736 std::vector<std::string>
741 return std::vector<std::string>();
746 std::vector<std::string> comps;
747 comps.reserve(
store.size());
748 for (IoCompStore_t::const_iterator
753 comps.push_back(jtr->first);
764 CompTuple_t::const_iterator itr =
m_ntuple.
comp.find(stepName);
771 if (jtr ==
store.end()) {
774 return &(jtr->second);
788 if (jtr ==
store.end()) {
791 return &(jtr->second);
804 const_cast<char*
>(
"domains_db"),
807 PMON_WARNING(
"Problem on python side for domains_db() !!");
811 if (!PyDict_Check(
db)) {
817 PyObject *py_domain = PyDict_GetItemString
819 const_cast<char*
>(
compName.c_str()));
826 #if PY_MAJOR_VERSION < 3
827 if (!PyString_Check(py_domain)) {
828 PMON_WARNING(
"domains_db() returned a non-string for component ["
834 domain = std::string(PyString_AS_STRING(py_domain));
837 if (!PyUnicode_Check(py_domain)) {
838 PMON_WARNING(
"domains_db() returned a non-unicode for component ["
844 domain = std::string(PyUnicode_AsUTF8(py_domain));
860 <<
"Entering handle(): "
862 <<
" Incidence type: " << inc.type() <<
endmsg
863 <<
" from: " << inc.source() <<
endmsg;
866 if ( inc.type() == IncidentType::SvcPostFinalize ) {
880 const IInterface* iowner )
882 const INamedInterface* owner =
dynamic_cast<const INamedInterface*
>(iowner);
883 if ( !owner ) {
throw std::bad_cast();
897 const IInterface* iowner )
899 const INamedInterface* owner =
dynamic_cast<const INamedInterface*
>(iowner);
900 if ( !owner ) {
throw std::bad_cast();
914 const IInterface* iowner )
916 const INamedInterface* owner =
dynamic_cast<const INamedInterface*
>(iowner);
917 if ( !owner ) {
throw std::bad_cast();
931 const IInterface* iowner )
933 const INamedInterface* owner =
dynamic_cast<const INamedInterface*
>(iowner);
934 if ( !owner ) {
throw std::bad_cast();
948 const IInterface* iowner )
950 const INamedInterface* owner =
dynamic_cast<const INamedInterface*
>(iowner);
951 if ( !owner ) {
throw std::bad_cast();
963 const std::pair<double,double>& ,
965 const IInterface* iowner )
967 const INamedInterface* owner =
dynamic_cast<const INamedInterface*
>(iowner);
968 if ( !owner ) {
throw std::bad_cast();
981 const AIDA::IBaseHistogram*
var,
982 const std::string&
desc,
983 const IInterface* owner )
985 std::ostringstream
err;
986 err <<
"PerfMonSvc::declareInfo( "
987 <<
"name = [" <<
name <<
"], "
988 <<
"hist = [" <<
var <<
"], "
989 <<
"descr = [" <<
desc <<
"], "
990 <<
"owner = [" << owner <<
"] )\n"
991 <<
"Not implemented !"
994 throw std::runtime_error(
err.str() );
998 const std::string&
format,
1000 const std::string&
desc,
1001 const IInterface* owner )
1003 std::ostringstream
err;
1004 err <<
"PerfMonSvc::declareInfo( "
1005 <<
"name = [" <<
name <<
"], "
1006 <<
"fmt = [" <<
format <<
"], "
1007 <<
"var = [" <<
var <<
"], "
1008 <<
"size= [" <<
size <<
"], "
1009 <<
"descr = [" <<
desc <<
"], "
1010 <<
"owner = [" << owner <<
"] )\n"
1011 <<
"Not implemented !"
1014 throw std::runtime_error(
err.str() );
1019 const StatEntity&
var,
1020 const std::string&
desc,
1021 const IInterface* owner)
1023 std::ostringstream
err;
1024 err <<
"PerfMonSvc::declareInfo( "
1025 <<
"name = [" <<
name <<
"], "
1026 <<
"var = [" <<
var <<
"], "
1027 <<
"descr = [" <<
desc <<
"], "
1028 <<
"owner = [" << owner <<
"] )\n"
1029 <<
"Not implemented !"
1032 throw std::runtime_error(
err.str() );
1036 const IInterface* iowner )
1038 const INamedInterface* owner =
dynamic_cast<const INamedInterface*
>(iowner);
1041 <<
"Requested to undeclare info from un-registered owner ["
1044 throw std::bad_cast();
1048 <<
"Could not find nor erase MonInfo of name [" <<
name <<
"] "
1049 <<
"registered with owner [" << owner <<
" (" << owner->name() <<
")] !"
1056 const INamedInterface* owner =
dynamic_cast<const INamedInterface*
>(iowner);
1059 <<
"Requested to undeclare info from un-registered owner ["
1062 throw std::bad_cast();
1066 <<
"Could not undeclare all infos "
1067 <<
"registered with owner [" << owner <<
" (" << owner->name() <<
")] !"
1089 const std::string pmon_slice =
"PerfMonSlice";
1090 const std::string usr_step_name =
"usr";
1093 bool do_mon(
int lvl,
1094 const std::string& stepName,
1097 return (lvl < 0 || lvl > 10 ||
1104 stepName == usr_step_name);
1110 const std::string& stepName,
1111 const std::string& )
1114 ((lvl < 0 || lvl > 10 ) &&
1121 stepName == usr_step_name;
1132 stopAud(
"ini",
"PerfMonSlice" );
1135 m_nalgs = mgr->getAlgorithms().size();
1153 <<
" [vmem="<<vmem/1024.0<<
"mb, rss="
1154 <<rss/1024.0<<
"mb, malloc="<<PMonSD::get_malloc_kb()/1024.0
1179 stopAud(
"evt",
"PerfMonSlice" );
1201 <<
" [vmem="<<vmem/1024.0<<
"mb, rss="
1202 <<rss/1024.0<<
"mb, malloc="<<PMonSD::get_malloc_kb()/1024.0
1242 int buf_sz = asprintf
1245 stepName.c_str(),
compName.c_str(),
1247 c.cpu.user,
c.cpu.sys,
c.cpu.real,
c.cpu.rt_cpu,
1248 c.mem.vmem[0],
c.mem.rss[0],
c.mem.mall[0],
1249 ((
unsigned long)
c.mem.nmall[0]),
1250 ((
unsigned long)
c.mem.nfree[0])
1257 const std::string stream_name =
m_outFileName.value()+
".pmon.stream";
1259 PMON_INFO(
"re-opening pmon-stream file [" << stream_name <<
"]...");
1261 O_WRONLY | O_APPEND,
1262 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
1265 PMON_ERROR(
"could not re-open pmon-stream file ["
1266 << stream_name <<
"] !");
1282 bool alertVmem =
false;
1297 stats.cpu +=
c.cpu.user +
c.cpu.sys;
1298 stats.cpu_user +=
c.cpu.user;
1299 stats.cpu_sys +=
c.cpu.sys;
1300 stats.real +=
c.cpu.real;
1301 stats.rt +=
c.cpu.rt_cpu;
1302 stats.vmem +=
c.mem.vmem[1];
1303 stats.malloc +=
c.mem.mall[1] -
c.mem.mall[0];
1304 stats.nalloc +=
c.mem.nmall[1]-
c.mem.nmall[0];
1335 asprintf(&hdr,
"[%s] ", stepName.c_str());
1355 "alloc= +%lu -%lu %8.3f kb " \
1358 c.cpu.user+
c.cpu.sys,
1359 c.mem.vmem[1]/1024.,
1360 c.mem.dVmem()/1024.,
1361 ((
unsigned long)
c.mem.dNMall()),
1362 ((
unsigned long)
c.mem.dNFree()),
1363 (
float)
c.mem.dMall(),
1391 int buf_sz = asprintf
1394 stepName.c_str(),
compName.c_str(),
1396 c.cpu.user,
c.cpu.sys,
c.cpu.real,
c.cpu.rt_cpu,
1397 c.mem.vmem[1],
c.mem.rss[1],
c.mem.mall[1],
1398 ((
unsigned long)
c.mem.nmall[1]),
1399 ((
unsigned long)
c.mem.nfree[1])
1416 for (std::size_t
i = 0,
imax = ionames.size();
1419 const std::string& ioname = ionames[
i];
1420 const std::string p2t = std::string(
"cObj_")+ioname;
1421 const std::string p2tr= std::string(
"cObjR_")+ioname;
1422 const std::string t2p = std::string(
"cRep_")+ioname;
1427 c.r.user = (
float)
m_chrono->chronoDelta(p2t, IChronoStatSvc::USER);
1428 c.r.sys = (
float)
m_chrono->chronoDelta(p2t, IChronoStatSvc::KERNEL);
1429 c.r.real = (
float)
m_chrono->chronoDelta(p2t, IChronoStatSvc::ELAPSED);
1433 c.rr.user = (
float)
m_chrono->chronoDelta(p2tr, IChronoStatSvc::USER);
1434 c.rr.sys = (
float)
m_chrono->chronoDelta(p2tr, IChronoStatSvc::KERNEL);
1435 c.rr.real = (
float)
m_chrono->chronoDelta(p2tr, IChronoStatSvc::ELAPSED);
1439 c.w.user = (
float)
m_chrono->chronoDelta(t2p, IChronoStatSvc::USER);
1440 c.w.sys = (
float)
m_chrono->chronoDelta(t2p, IChronoStatSvc::KERNEL);
1441 c.w.real = (
float)
m_chrono->chronoDelta(t2p, IChronoStatSvc::ELAPSED);
1445 int buf_sz = asprintf
1448 "io", ioname.c_str(),
1449 c.r.user,
c.r.sys,
c.r.real,
c.r.rt_cpu,
1450 c.rr.user,
c.rr.sys,
c.rr.real,
c.rr.rt_cpu,
1451 c.w.user,
c.w.sys,
c.w.real,
c.w.rt_cpu
1458 const std::string ioname =
"commitOutput";
1459 c.w.user = (
float)
m_chrono->chronoDelta(ioname, IChronoStatSvc::USER);
1460 c.w.sys = (
float)
m_chrono->chronoDelta(ioname, IChronoStatSvc::KERNEL);
1461 c.w.real = (
float)
m_chrono->chronoDelta(ioname, IChronoStatSvc::ELAPSED);
1465 int buf_sz = asprintf
1468 "io",
"PerfMonSliceIo",
1469 c.r.user,
c.r.sys,
c.r.real,
c.r.rt_cpu,
1470 c.rr.user,
c.rr.sys,
c.rr.real,
c.rr.rt_cpu,
1471 c.w.user,
c.w.sys,
c.w.real,
c.w.rt_cpu
1485 #include "GaudiKernel/Timing.h"
1487 #include <mach/task.h>
1488 #include <mach/mach_init.h>
1495 const System::TimeType MyUnit = System::milliSec;
1503 cpu.
user =
static_cast<float>(System::userTime (MyUnit)) - cpu.
user;
1504 cpu.
sys =
static_cast<float>(System::kernelTime (MyUnit)) - cpu.
sys;
1505 cpu.
real =
static_cast<float>(System::ellapsedTime(MyUnit)) - cpu.
real;
1511 static const long pg_size = sysconf(_SC_PAGESIZE);
1525 if (
evt->step == 0) {
1527 }
else if (
evt->step == 1) {