Skip to content

Commit

Permalink
Use single metric multi-value metric for process performance (#199)
Browse files Browse the repository at this point in the history
  • Loading branch information
awegrzyn authored May 14, 2020
1 parent 0795fea commit 008f13a
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 43 deletions.
13 changes: 8 additions & 5 deletions include/Monitoring/ProcessMonitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,8 @@ class ProcessMonitor
/// Default destructor
~ProcessMonitor() = default;

/// Retrieves memory usage (%)
Metric getMemoryUsage();

/// Retrieves CPU usage (%) and number of context switches during the interval
std::vector<Metric> getCpuAndContexts();
/// Return performance metrics
Metric getPerformanceMetrics();

private:
/// PIDs that are monitored
Expand All @@ -64,6 +61,12 @@ class ProcessMonitor

/// Timestamp when process monitoring was executed last time
std::chrono::high_resolution_clock::time_point mTimeLastRun;

/// Retrieves memory usage (%)
double getMemoryUsage();

/// Retrieves CPU usage (%) and number of context switches during the interval
Metric getCpuAndContexts();
};

} // namespace monitoring
Expand Down
25 changes: 1 addition & 24 deletions src/Monitoring.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -134,36 +134,13 @@ void Monitoring::pushLoop()
std::this_thread::sleep_for(std::chrono::milliseconds(100));
while (mMonitorRunning) {
if (mProcessMonitoringInterval != 0 && (loopCount % (mProcessMonitoringInterval * 10)) == 0) {
transmit(mProcessMonitor->getCpuAndContexts());
#ifdef O2_MONITORING_OS_LINUX
transmit(mProcessMonitor->getMemoryUsage());
#endif
transmit(mProcessMonitor->getPerformanceMetrics());
}

/*if (mAutoPushInterval != 0 && (loopCount % (mAutoPushInterval * 10)) == 0) {
std::vector<Metric> metrics;
for (auto metric : mPushStore) {
metric.resetTimestamp();
metrics.push_back(metric);
}
transmit(std::move(metrics));
}*/
std::this_thread::sleep_for(std::chrono::milliseconds(100));
(loopCount >= 600) ? loopCount = 0 : loopCount++;
}
}

/*ComplexMetric& Monitoring::getAutoPushMetric(std::string name, unsigned int interval)
{
if (!mMonitorRunning) {
mMonitorRunning = true;
mMonitorThread = std::thread(&Monitoring::pushLoop, this);
mAutoPushInterval = interval;
}
mPushStore.emplace_back(std::variant<int, std::string, double, uint64_t>{}, name);
return mPushStore.back();
}*/

void Monitoring::transmit(std::vector<Metric>&& metrics)
{
for (auto& backend : mBackends) {
Expand Down
27 changes: 17 additions & 10 deletions src/ProcessMonitor.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@ ProcessMonitor::ProcessMonitor()
#endif
}

Metric ProcessMonitor::getPerformanceMetrics()
{
auto metric = getCpuAndContexts();
#ifdef O2_MONITORING_OS_LINUX
metric.addValue(getMemoryUsage(), "memory_pct");
#endif
return metric;
}

void ProcessMonitor::setTotalMemory()
{
std::ifstream memInfo("/proc/meminfo");
Expand All @@ -39,7 +48,7 @@ void ProcessMonitor::setTotalMemory()
mTotalMemory = std::stoi(tokens[1]);
}

Metric ProcessMonitor::getMemoryUsage()
double ProcessMonitor::getMemoryUsage()
{
std::ifstream statusStream("/proc/self/status");
std::string rssString;
Expand All @@ -52,30 +61,28 @@ Metric ProcessMonitor::getMemoryUsage()
std::istringstream iss(rssString);
std::vector<std::string> tokens{std::istream_iterator<std::string>{iss},
std::istream_iterator<std::string>{}};
return Metric{(std::stod(tokens[1]) * 100) / mTotalMemory, "memoryUsagePercentage"};
return (std::stod(tokens[1]) * 100) / mTotalMemory;
}

std::vector<Metric> ProcessMonitor::getCpuAndContexts()
Metric ProcessMonitor::getCpuAndContexts()
{
std::vector<Metric> metrics;
struct rusage currentUsage;
getrusage(RUSAGE_SELF, &currentUsage);
auto timeNow = std::chrono::high_resolution_clock::now();
double timePassed = std::chrono::duration_cast<std::chrono::microseconds>(timeNow - mTimeLastRun).count();
if (timePassed < 950) {
MonLogger::Get() << "[WARN] Do not invoke Process Monitor more frequent then every 1s" << MonLogger::End();
return {};
return {"processPerformance"};
}
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;

metrics.emplace_back(Metric{
static_cast<double>(std::round(fractionCpuUsed * 100.0 * 100.0) / 100.0), "cpuUsedPercentage"});
metrics.emplace_back(Metric{
static_cast<uint64_t>(currentUsage.ru_nivcsw - mPreviousGetrUsage.ru_nivcsw), "involuntaryContextSwitches"});
Metric metric{"processPerformance"};
metric.addValue(static_cast<double>(std::round(fractionCpuUsed * 100.0 * 100.0) / 100.0), "cpu_user_pct");
metric.addValue(static_cast<uint64_t>(currentUsage.ru_nivcsw - mPreviousGetrUsage.ru_nivcsw), "involuntary_context_switches");

mTimeLastRun = timeNow;
mPreviousGetrUsage = currentUsage;
return metrics;
return metric;
}

} // namespace monitoring
Expand Down
5 changes: 1 addition & 4 deletions test/testProcessMonitor.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,7 @@ namespace Test
BOOST_AUTO_TEST_CASE(createProcessMonitor)
{
o2::monitoring::ProcessMonitor processMonitor;
processMonitor.getCpuAndContexts();
#ifdef O2_MONITORING_OS_LINUX
processMonitor.getMemoryUsage();
#endif
processMonitor.getPerformanceMetrics();
}

BOOST_AUTO_TEST_CASE(monitorProcess)
Expand Down

0 comments on commit 008f13a

Please sign in to comment.