1111#include < cmath>
1212#include < fstream>
1313#include < utility>
14+ #include < numeric>
1415
1516namespace o2
1617{
@@ -21,68 +22,135 @@ namespace monitoring
2122ProcessMonitor::ProcessMonitor ()
2223{
2324 mPid = static_cast <unsigned int >(::getpid ());
24- getrusage (RUSAGE_SELF, &mPreviousGetrUsage );
2525 mTimeLastRun = std::chrono::high_resolution_clock::now ();
26+ getrusage (RUSAGE_SELF, &mPreviousGetrUsage );
2627#ifdef O2_MONITORING_OS_LINUX
2728 setTotalMemory ();
2829#endif
2930}
3031
31- Metric ProcessMonitor::getPerformanceMetrics ()
32+ void ProcessMonitor::init ()
3233{
33- auto metric = getCpuAndContexts ();
34- #ifdef O2_MONITORING_OS_LINUX
35- metric.addValue (getMemoryUsage (), " memory_pct" );
36- #endif
37- return metric;
34+ mTimeLastRun = std::chrono::high_resolution_clock::now ();
35+ getrusage (RUSAGE_SELF, &mPreviousGetrUsage );
3836}
3937
4038void ProcessMonitor::setTotalMemory ()
4139{
4240 std::ifstream memInfo (" /proc/meminfo" );
4341 std::string totalString;
4442 std::getline (memInfo, totalString);
45- std::istringstream iss (totalString);
46- std::vector<std::string> tokens{std::istream_iterator<std::string>{iss},
47- std::istream_iterator<std::string>{}};
48- mTotalMemory = std::stoi (tokens[1 ]);
43+ mTotalMemory = splitStatusLineAndRetriveValue (totalString);
4944}
5045
51- double ProcessMonitor::getMemoryUsage ()
46+ std::vector<Metric> ProcessMonitor::getMemoryUsage ()
5247{
48+ std::vector<Metric> metrics;
5349 std::ifstream statusStream (" /proc/self/status" );
5450 std::string rssString;
5551 rssString.reserve (50 );
5652
53+ // Scan for VmSize
54+ for (unsigned i = 0 ; i < VM_SIZE_INDEX; ++i) {
55+ std::getline (statusStream, rssString);
56+ }
57+ auto vmSize = splitStatusLineAndRetriveValue (rssString);
58+ mVmSizeMeasurements .push_back (vmSize);
59+
60+ metrics.emplace_back ((vmSize * 100 ) / mTotalMemory , metricsNames[MEMORY_USAGE_PERCENTAGE]);
61+ metrics.emplace_back (vmSize, metricsNames[VIRTUAL_MEMORY_SIZE]);
62+
5763 // Scan for VmRSS
58- for (int i = 0 ; i < 18 ; i++ ) {
64+ for (unsigned i = 0 ; i < VM_RSS_INDEX - VM_SIZE_INDEX; ++i ) {
5965 std::getline (statusStream, rssString);
6066 }
61- std::istringstream iss (rssString);
62- std::vector<std::string> tokens{std::istream_iterator<std::string>{iss},
63- std::istream_iterator<std::string>{}};
64- return (std::stod (tokens[1 ]) * 100 ) / mTotalMemory ;
67+
68+ auto vmRSS = splitStatusLineAndRetriveValue (rssString);
69+ metrics.emplace_back (vmRSS, metricsNames[RESIDENT_SET_SIZE]);
70+ mVmRssMeasurements .push_back (vmRSS);
71+
72+ return metrics;
6573}
6674
67- Metric ProcessMonitor::getCpuAndContexts ()
75+ std::vector< Metric> ProcessMonitor::getCpuAndContexts ()
6876{
77+ std::vector<Metric> metrics;
6978 struct rusage currentUsage;
7079 getrusage (RUSAGE_SELF, ¤tUsage);
7180 auto timeNow = std::chrono::high_resolution_clock::now ();
7281 double timePassed = std::chrono::duration_cast<std::chrono::microseconds>(timeNow - mTimeLastRun ).count ();
7382 if (timePassed < 950 ) {
7483 MonLogger::Get () << " [WARN] Do not invoke Process Monitor more frequent then every 1s" << MonLogger::End ();
75- return {" processPerformance" };
84+ metrics.emplace_back (" processPerformance" );
85+ return metrics;
7686 }
77- double fractionCpuUsed = (currentUsage.ru_utime .tv_sec * 1000000.0 + currentUsage.ru_utime .tv_usec - (mPreviousGetrUsage .ru_utime .tv_sec * 1000000.0 + mPreviousGetrUsage .ru_utime .tv_usec ) + currentUsage.ru_stime .tv_sec * 1000000.0 + currentUsage.ru_stime .tv_usec - (mPreviousGetrUsage .ru_stime .tv_sec * 1000000.0 + mPreviousGetrUsage .ru_stime .tv_usec )) / timePassed;
7887
79- Metric metric{" processPerformance" };
80- metric.addValue (static_cast <double >(std::round (fractionCpuUsed * 100.0 * 100.0 ) / 100.0 ), " cpu_used_pct" );
81- metric.addValue (static_cast <uint64_t >(currentUsage.ru_nivcsw - mPreviousGetrUsage .ru_nivcsw ), " involuntary_context_switches" );
88+ uint64_t cpuUsedInMicroSeconds = currentUsage.ru_utime .tv_sec * 1000000.0 + currentUsage.ru_utime .tv_usec - (mPreviousGetrUsage .ru_utime .tv_sec * 1000000.0 + mPreviousGetrUsage .ru_utime .tv_usec ) + currentUsage.ru_stime .tv_sec * 1000000.0 + currentUsage.ru_stime .tv_usec - (mPreviousGetrUsage .ru_stime .tv_sec * 1000000.0 + mPreviousGetrUsage .ru_stime .tv_usec );
89+ double fractionCpuUsed = cpuUsedInMicroSeconds / timePassed;
90+
91+ double cpuUsedPerctange = std::round (fractionCpuUsed * 100.0 * 100.0 ) / 100.0 ;
92+ mCpuPerctange .push_back (cpuUsedPerctange);
93+ mCpuMicroSeconds .push_back (cpuUsedInMicroSeconds);
94+
95+ metrics.emplace_back (Metric{cpuUsedPerctange, metricsNames[CPU_USED_PERCENTAGE]});
96+ metrics.emplace_back (Metric{
97+ static_cast <uint64_t >(currentUsage.ru_nivcsw - mPreviousGetrUsage .ru_nivcsw ), metricsNames[INVOLUNTARY_CONTEXT_SWITCHING]});
98+ metrics.emplace_back (cpuUsedInMicroSeconds, metricsNames[CPU_USED_ABSOLUTE]);
8299
83100 mTimeLastRun = timeNow;
84101 mPreviousGetrUsage = currentUsage;
85- return metric;
102+ return metrics;
103+ }
104+
105+ double ProcessMonitor::splitStatusLineAndRetriveValue (const std::string& line) const
106+ {
107+ std::istringstream iss (line);
108+ std::vector<std::string> tokens{std::istream_iterator<std::string>{iss},
109+ std::istream_iterator<std::string>{}};
110+ return std::stod (tokens[1 ]);
111+ }
112+
113+ std::vector<Metric> ProcessMonitor::getPerformanceMetrics ()
114+ {
115+ auto metrics = getCpuAndContexts ();
116+ #ifdef O2_MONITORING_OS_LINUX
117+ auto memoryMetrics = getMemoryUsage ();
118+ std::move (memoryMetrics.begin (), memoryMetrics.end (), std::back_inserter (metrics));
119+ #endif
120+ return metrics;
121+ }
122+
123+ std::vector<Metric> ProcessMonitor::makeLastMeasurementAndGetMetrics ()
124+ {
125+ std::vector<Metric> metrics;
126+ getCpuAndContexts ();
127+ #ifdef O2_MONITORING_OS_LINUX
128+ getMemoryUsage ();
129+
130+ auto avgVmRSS = std::accumulate (mVmRssMeasurements .begin (), mVmRssMeasurements .end (), 0.0 ) /
131+ mVmRssMeasurements .size ();
132+
133+ metrics.emplace_back (avgVmRSS, metricsNames[AVG_RESIDENT_SET_SIZE]);
134+
135+ auto avgVmSize = std::accumulate (mVmSizeMeasurements .begin (), mVmSizeMeasurements .end (), 0.0 ) /
136+ mVmSizeMeasurements .size ();
137+ metrics.emplace_back (avgVmSize, metricsNames[AVG_VIRTUAL_MEMORY_SIZE]);
138+ #endif
139+
140+ auto avgCpuUsage = std::accumulate (mCpuPerctange .begin (), mCpuPerctange .end (), 0.0 ) /
141+ mCpuPerctange .size ();
142+ uint64_t accumulationOfCpuTimeConsumption = std::accumulate (mCpuMicroSeconds .begin (),
143+ mCpuMicroSeconds .end (), 0UL );
144+
145+ metrics.emplace_back (avgCpuUsage, metricsNames[AVG_CPU_USED_PERCENTAGE]);
146+ metrics.emplace_back (accumulationOfCpuTimeConsumption, metricsNames[ACCUMULATED_CPU_TIME]);
147+
148+ return metrics;
149+ }
150+
151+ std::vector<std::string> ProcessMonitor::getAvailableMetricsNames ()
152+ {
153+ return {std::begin (metricsNames), std::end (metricsNames)};
86154}
87155
88156} // namespace monitoring
0 commit comments