| File: | framework/utilities/src/Utils.cc |
| Warning: | line 64, column 5 Value of 'errno' was not checked and may be overwritten by function 'fscanf' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /************************************************************************** | |||
| 2 | * basf2 (Belle II Analysis Software Framework) * | |||
| 3 | * Author: The Belle II Collaboration * | |||
| 4 | * * | |||
| 5 | * See git log for contributors and copyright holders. * | |||
| 6 | * This file is licensed under LGPL-3.0, see LICENSE.md. * | |||
| 7 | **************************************************************************/ | |||
| 8 | // weird bug in intel compiler and or boost::process: If we include boost | |||
| 9 | // process intel compile fails. It seems that including sys/wait.h after | |||
| 10 | // other c++ std:: headers triggers a weird behavior failing two static | |||
| 11 | // asserts. We work around that by including it right away | |||
| 12 | #include <sys/wait.h> | |||
| 13 | ||||
| 14 | #include <framework/utilities/Utils.h> | |||
| 15 | ||||
| 16 | #include <framework/gearbox/Unit.h> | |||
| 17 | #include <framework/logging/Logger.h> | |||
| 18 | ||||
| 19 | #include <boost/process/v1/args.hpp> | |||
| 20 | #include <boost/process/v1/child.hpp> | |||
| 21 | #include <boost/process/v1/io.hpp> | |||
| 22 | #include <boost/process/v1/pipe.hpp> | |||
| 23 | #include <boost/process/v1/search_path.hpp> | |||
| 24 | ||||
| 25 | #include <sys/time.h> | |||
| 26 | #include <unistd.h> | |||
| 27 | ||||
| 28 | #include <cstdio> | |||
| 29 | #include <iomanip> | |||
| 30 | #include <utility> | |||
| 31 | #include <filesystem> | |||
| 32 | ||||
| 33 | using namespace Belle2; | |||
| 34 | ||||
| 35 | namespace { | |||
| 36 | /** get the Virtual and Resident memory size in KB | |||
| 37 | * | |||
| 38 | * This is done by reading /proc/PID/statm (kept open between calls) | |||
| 39 | * | |||
| 40 | * this is significantly faster than using TSystem::GetProcInfo() | |||
| 41 | * | |||
| 42 | * @return pair with virtual memory size in the first and resident memory | |||
| 43 | * size in the second entry. | |||
| 44 | */ | |||
| 45 | std::pair<unsigned long, unsigned long> getStatmSize() | |||
| 46 | { | |||
| 47 | /** page size of system */ | |||
| 48 | const static long pageSizeKb = sysconf(_SC_PAGESIZE_SC_PAGESIZE) / 1024; | |||
| 49 | static FILE* stream = nullptr; | |||
| 50 | static int pid = 0; | |||
| 51 | int currentPid = getpid(); | |||
| 52 | if (currentPid != pid) { | |||
| 53 | pid = currentPid; | |||
| 54 | std::string statm = "/proc/" + std::to_string(pid) + "/statm"; | |||
| 55 | stream = fopen(statm.c_str(), "r"); | |||
| 56 | // If we use buffering we might get the same value each time we read so | |||
| 57 | // disable buffering | |||
| 58 | setvbuf(stream, nullptr, _IONBF2, 0); | |||
| 59 | } | |||
| 60 | unsigned long vmSizePages{0}; | |||
| 61 | unsigned long rssPages{0}; | |||
| 62 | if (!stream
| |||
| 63 | rewind(stream); | |||
| 64 | fscanf(stream, "%lu %lu", &vmSizePages, &rssPages); | |||
| ||||
| 65 | return std::make_pair(vmSizePages * pageSizeKb, rssPages * pageSizeKb); | |||
| 66 | } | |||
| 67 | } | |||
| 68 | ||||
| 69 | namespace Belle2::Utils { | |||
| 70 | ||||
| 71 | double getClock() | |||
| 72 | { | |||
| 73 | timespec ts; | |||
| 74 | clock_gettime(CLOCK_REALTIME0, &ts); | |||
| 75 | return (ts.tv_sec * Unit::s) + (ts.tv_nsec * Unit::ns); | |||
| 76 | } | |||
| 77 | double getCPUClock() | |||
| 78 | { | |||
| 79 | timespec ts; | |||
| 80 | clock_gettime(CLOCK_PROCESS_CPUTIME_ID2, &ts); | |||
| 81 | return (ts.tv_sec * Unit::s) + (ts.tv_nsec * Unit::ns); | |||
| 82 | } | |||
| 83 | ||||
| 84 | unsigned long getVirtualMemoryKB() | |||
| 85 | { | |||
| 86 | return getStatmSize().first; | |||
| 87 | } | |||
| 88 | ||||
| 89 | unsigned long getRssMemoryKB() | |||
| 90 | { | |||
| 91 | return getStatmSize().second; | |||
| ||||
| 92 | } | |||
| 93 | ||||
| 94 | Timer::Timer(std::string text): | |||
| 95 | m_startTime(getClock()), | |||
| 96 | m_text(std::move(text)) | |||
| 97 | { } | |||
| 98 | ||||
| 99 | Timer::~Timer() | |||
| 100 | { | |||
| 101 | double elapsed = (getClock() - m_startTime) / Unit::ms; | |||
| 102 | B2INFO(m_text << " " << std::fixed << std::setprecision(3) << elapsed << " ms")do { if (Belle2::LogSystem::Instance().isLevelEnabled(Belle2:: LogConfig::c_Info, 0, "framework")) { { LogVariableStream varStream ; varStream << m_text << " " << std::fixed << std::setprecision(3) << elapsed << " ms"; Belle2 ::LogSystem::Instance().sendMessage(Belle2::LogMessage(Belle2 ::LogConfig::c_Info, std::move(varStream), "framework", __PRETTY_FUNCTION__ , "framework/utilities/src/Utils.cc", 102, 0)); }; } } while( false); | |||
| 103 | } | |||
| 104 | ||||
| 105 | std::string getCommandOutput(const std::string& command, const std::vector<std::string>& arguments, | |||
| 106 | bool searchPath) | |||
| 107 | { | |||
| 108 | namespace bp = boost::process::v1; | |||
| 109 | auto cmd = searchPath ? bp::search_path(command) : boost::filesystem::path(command); | |||
| 110 | bp::ipstream cmdOut; | |||
| 111 | bp::child child(cmd, bp::args(arguments), bp::std_in.close(), bp::std_out > cmdOut); | |||
| 112 | char buffer[4096]; | |||
| 113 | std::string result; | |||
| 114 | while (child.running() && cmdOut.read(buffer, sizeof(buffer))) { | |||
| 115 | result.append(buffer, sizeof(buffer)); | |||
| 116 | } | |||
| 117 | if (cmdOut.gcount()) result.append(buffer, cmdOut.gcount()); | |||
| 118 | return result; | |||
| 119 | } | |||
| 120 | } |