Initial setup for CLion
This commit is contained in:
206
engines/OpenVINOEngine/src/monitors/cpu_monitor.cpp
Normal file
206
engines/OpenVINOEngine/src/monitors/cpu_monitor.cpp
Normal file
@@ -0,0 +1,206 @@
|
||||
// Copyright (C) 2019-2024 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "monitors/cpu_monitor.h"
|
||||
|
||||
#include <algorithm>
|
||||
#ifdef _WIN32
|
||||
#include "query_wrapper.h"
|
||||
#include <string>
|
||||
#include <system_error>
|
||||
#include <PdhMsg.h>
|
||||
#include <Windows.h>
|
||||
|
||||
namespace {
|
||||
const std::size_t nCores = []() {
|
||||
SYSTEM_INFO sysinfo;
|
||||
GetSystemInfo(&sysinfo);
|
||||
return sysinfo.dwNumberOfProcessors;
|
||||
}();
|
||||
}
|
||||
|
||||
class CpuMonitor::PerformanceCounter {
|
||||
public:
|
||||
PerformanceCounter() : coreTimeCounters(nCores) {
|
||||
PDH_STATUS status;
|
||||
for (std::size_t i = 0; i < nCores; ++i) {
|
||||
std::wstring fullCounterPath{L"\\Processor(" + std::to_wstring(i) + L")\\% Processor Time"};
|
||||
status = PdhAddCounterW(query, fullCounterPath.c_str(), 0, &coreTimeCounters[i]);
|
||||
if (ERROR_SUCCESS != status) {
|
||||
throw std::system_error(status, std::system_category(), "PdhAddCounterW() failed");
|
||||
}
|
||||
status = PdhSetCounterScaleFactor(coreTimeCounters[i], -2); // scale counter to [0, 1]
|
||||
if (ERROR_SUCCESS != status) {
|
||||
throw std::system_error(status, std::system_category(), "PdhSetCounterScaleFactor() failed");
|
||||
}
|
||||
}
|
||||
status = PdhCollectQueryData(query);
|
||||
if (ERROR_SUCCESS != status) {
|
||||
throw std::system_error(status, std::system_category(), "PdhCollectQueryData() failed");
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<double> getCpuLoad() {
|
||||
PDH_STATUS status;
|
||||
status = PdhCollectQueryData(query);
|
||||
if (ERROR_SUCCESS != status) {
|
||||
throw std::system_error(status, std::system_category(), "PdhCollectQueryData() failed");
|
||||
}
|
||||
|
||||
PDH_FMT_COUNTERVALUE displayValue;
|
||||
std::vector<double> cpuLoad(coreTimeCounters.size());
|
||||
for (std::size_t i = 0; i < coreTimeCounters.size(); ++i) {
|
||||
status = PdhGetFormattedCounterValue(coreTimeCounters[i], PDH_FMT_DOUBLE, NULL,
|
||||
&displayValue);
|
||||
switch (status) {
|
||||
case ERROR_SUCCESS: break;
|
||||
// PdhGetFormattedCounterValue() can sometimes return PDH_CALC_NEGATIVE_DENOMINATOR for some reason
|
||||
case PDH_CALC_NEGATIVE_DENOMINATOR: return {};
|
||||
default:
|
||||
throw std::system_error(status, std::system_category(), "PdhGetFormattedCounterValue() failed");
|
||||
}
|
||||
if (PDH_CSTATUS_VALID_DATA != displayValue.CStatus && PDH_CSTATUS_NEW_DATA != displayValue.CStatus) {
|
||||
throw std::runtime_error("Error in counter data");
|
||||
}
|
||||
|
||||
cpuLoad[i] = displayValue.doubleValue;
|
||||
}
|
||||
return cpuLoad;
|
||||
}
|
||||
|
||||
private:
|
||||
QueryWrapper query;
|
||||
std::vector<PDH_HCOUNTER> coreTimeCounters;
|
||||
};
|
||||
|
||||
#elif __linux__
|
||||
#include <chrono>
|
||||
#include <regex>
|
||||
#include <utility>
|
||||
#include <fstream>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace {
|
||||
const long clockTicks = sysconf(_SC_CLK_TCK);
|
||||
|
||||
const std::size_t nCores = sysconf(_SC_NPROCESSORS_CONF);
|
||||
|
||||
std::vector<unsigned long> getIdleCpuStat() {
|
||||
std::vector<unsigned long> idleCpuStat(nCores);
|
||||
std::ifstream procStat("/proc/stat");
|
||||
std::string line;
|
||||
std::smatch match;
|
||||
std::regex coreJiffies("^cpu(\\d+)\\s+"
|
||||
"(\\d+)\\s+"
|
||||
"(\\d+)\\s+"
|
||||
"(\\d+)\\s+"
|
||||
"(\\d+)\\s+" // idle
|
||||
"(\\d+)"); // iowait
|
||||
|
||||
while (std::getline(procStat, line)) {
|
||||
if (std::regex_search(line, match, coreJiffies)) {
|
||||
// it doesn't handle overflow of sum and overflows of /proc/stat values
|
||||
unsigned long idleInfo = stoul(match[5]) + stoul(match[6]),
|
||||
coreId = stoul(match[1]);
|
||||
if (nCores <= coreId) {
|
||||
throw std::runtime_error("The number of cores has changed");
|
||||
}
|
||||
idleCpuStat[coreId] = idleInfo;
|
||||
}
|
||||
}
|
||||
return idleCpuStat;
|
||||
}
|
||||
}
|
||||
|
||||
class CpuMonitor::PerformanceCounter {
|
||||
public:
|
||||
PerformanceCounter() : prevIdleCpuStat{getIdleCpuStat()}, prevTimePoint{std::chrono::steady_clock::now()} {}
|
||||
|
||||
std::vector<double> getCpuLoad() {
|
||||
std::vector<unsigned long> idleCpuStat = getIdleCpuStat();
|
||||
auto timePoint = std::chrono::steady_clock::now();
|
||||
// don't update data too frequently which may result in negative values for cpuLoad.
|
||||
// It may happen when collectData() is called just after setHistorySize().
|
||||
if (timePoint - prevTimePoint > std::chrono::milliseconds{100}) {
|
||||
std::vector<double> cpuLoad(nCores);
|
||||
for (std::size_t i = 0; i < idleCpuStat.size(); ++i) {
|
||||
double idleDiff = idleCpuStat[i] - prevIdleCpuStat[i];
|
||||
typedef std::chrono::duration<double, std::chrono::seconds::period> Sec;
|
||||
cpuLoad[i] = 1.0
|
||||
- idleDiff / clockTicks / std::chrono::duration_cast<Sec>(timePoint - prevTimePoint).count();
|
||||
}
|
||||
prevIdleCpuStat = std::move(idleCpuStat);
|
||||
prevTimePoint = timePoint;
|
||||
return cpuLoad;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
private:
|
||||
std::vector<unsigned long> prevIdleCpuStat;
|
||||
std::chrono::steady_clock::time_point prevTimePoint;
|
||||
};
|
||||
|
||||
#else
|
||||
// not implemented
|
||||
namespace {
|
||||
const std::size_t nCores{0};
|
||||
}
|
||||
|
||||
class CpuMonitor::PerformanceCounter {
|
||||
public:
|
||||
std::vector<double> getCpuLoad() {return {};};
|
||||
};
|
||||
#endif
|
||||
|
||||
CpuMonitor::CpuMonitor() :
|
||||
samplesNumber{0},
|
||||
historySize{0},
|
||||
cpuLoadSum(nCores, 0) {}
|
||||
|
||||
// PerformanceCounter is incomplete in header and destructor can't be defined implicitly
|
||||
CpuMonitor::~CpuMonitor() = default;
|
||||
|
||||
void CpuMonitor::setHistorySize(std::size_t size) {
|
||||
if (0 == historySize && 0 != size) {
|
||||
performanceCounter.reset(new PerformanceCounter);
|
||||
} else if (0 != historySize && 0 == size) {
|
||||
performanceCounter.reset();
|
||||
}
|
||||
historySize = size;
|
||||
std::ptrdiff_t newSize = static_cast<std::ptrdiff_t>(min(size, cpuLoadHistory.size()));
|
||||
cpuLoadHistory.erase(cpuLoadHistory.begin(), cpuLoadHistory.end() - newSize);
|
||||
}
|
||||
|
||||
void CpuMonitor::collectData() {
|
||||
std::vector<double> cpuLoad = performanceCounter->getCpuLoad();
|
||||
|
||||
if (!cpuLoad.empty()) {
|
||||
for (std::size_t i = 0; i < cpuLoad.size(); ++i) {
|
||||
cpuLoadSum[i] += cpuLoad[i];
|
||||
}
|
||||
++samplesNumber;
|
||||
|
||||
cpuLoadHistory.push_back(std::move(cpuLoad));
|
||||
if (cpuLoadHistory.size() > historySize) {
|
||||
cpuLoadHistory.pop_front();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t CpuMonitor::getHistorySize() const {
|
||||
return historySize;
|
||||
}
|
||||
|
||||
std::deque<std::vector<double>> CpuMonitor::getLastHistory() const {
|
||||
return cpuLoadHistory;
|
||||
}
|
||||
|
||||
std::vector<double> CpuMonitor::getMeanCpuLoad() const {
|
||||
std::vector<double> meanCpuLoad;
|
||||
meanCpuLoad.reserve(cpuLoadSum.size());
|
||||
for (double coreLoad : cpuLoadSum) {
|
||||
meanCpuLoad.push_back(samplesNumber ? coreLoad / samplesNumber : 0);
|
||||
}
|
||||
return meanCpuLoad;
|
||||
}
|
||||
213
engines/OpenVINOEngine/src/monitors/memory_monitor.cpp
Normal file
213
engines/OpenVINOEngine/src/monitors/memory_monitor.cpp
Normal file
@@ -0,0 +1,213 @@
|
||||
// Copyright (C) 2019-2024 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "monitors/memory_monitor.h"
|
||||
|
||||
struct MemState {
|
||||
double memTotal, usedMem, usedSwap;
|
||||
};
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "query_wrapper.h"
|
||||
#include <algorithm>
|
||||
#define PSAPI_VERSION 2
|
||||
#include <system_error>
|
||||
#include <Windows.h>
|
||||
#include <PdhMsg.h>
|
||||
#include <Psapi.h>
|
||||
|
||||
namespace {
|
||||
double getMemTotal() {
|
||||
PERFORMANCE_INFORMATION performanceInformation;
|
||||
if (!GetPerformanceInfo(&performanceInformation, sizeof(performanceInformation))) {
|
||||
throw std::runtime_error("GetPerformanceInfo() failed");
|
||||
}
|
||||
return static_cast<double>(performanceInformation.PhysicalTotal * performanceInformation.PageSize)
|
||||
/ (1024 * 1024 * 1024);
|
||||
}
|
||||
}
|
||||
|
||||
class MemoryMonitor::PerformanceCounter {
|
||||
public:
|
||||
PerformanceCounter() {
|
||||
PDH_STATUS status = PdhAddCounterW(query, L"\\Paging File(_Total)\\% Usage", 0, &pagingFileUsageCounter);
|
||||
if (ERROR_SUCCESS != status) {
|
||||
throw std::system_error(status, std::system_category(), "PdhAddCounterW() failed");
|
||||
}
|
||||
status = PdhSetCounterScaleFactor(pagingFileUsageCounter, -2); // scale counter to [0, 1]
|
||||
if (ERROR_SUCCESS != status) {
|
||||
throw std::system_error(status, std::system_category(), "PdhSetCounterScaleFactor() failed");
|
||||
}
|
||||
}
|
||||
|
||||
MemState getMemState() {
|
||||
PERFORMANCE_INFORMATION performanceInformation;
|
||||
if (!GetPerformanceInfo(&performanceInformation, sizeof(performanceInformation))) {
|
||||
throw std::runtime_error("GetPerformanceInfo() failed");
|
||||
}
|
||||
|
||||
PDH_STATUS status;
|
||||
status = PdhCollectQueryData(query);
|
||||
if (ERROR_SUCCESS != status) {
|
||||
throw std::system_error(status, std::system_category(), "PdhCollectQueryData() failed");
|
||||
}
|
||||
PDH_FMT_COUNTERVALUE displayValue;
|
||||
status = PdhGetFormattedCounterValue(pagingFileUsageCounter, PDH_FMT_DOUBLE, NULL, &displayValue);
|
||||
if (ERROR_SUCCESS != status) {
|
||||
throw std::system_error(status, std::system_category(), "PdhGetFormattedCounterValue() failed");
|
||||
}
|
||||
if (PDH_CSTATUS_VALID_DATA != displayValue.CStatus && PDH_CSTATUS_NEW_DATA != displayValue.CStatus) {
|
||||
throw std::runtime_error("Error in counter data");
|
||||
}
|
||||
|
||||
double pagingFilesSize = static_cast<double>(
|
||||
(performanceInformation.CommitLimit - performanceInformation.PhysicalTotal)
|
||||
* performanceInformation.PageSize) / (1024 * 1024 * 1024);
|
||||
return {static_cast<double>(performanceInformation.PhysicalTotal * performanceInformation.PageSize)
|
||||
/ (1024 * 1024 * 1024),
|
||||
static_cast<double>(
|
||||
(performanceInformation.PhysicalTotal - performanceInformation.PhysicalAvailable)
|
||||
* performanceInformation.PageSize) / (1024 * 1024 * 1024),
|
||||
pagingFilesSize * displayValue.doubleValue};
|
||||
}
|
||||
private:
|
||||
QueryWrapper query;
|
||||
PDH_HCOUNTER pagingFileUsageCounter;
|
||||
};
|
||||
|
||||
#elif __linux__
|
||||
#include <fstream>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <regex>
|
||||
|
||||
namespace {
|
||||
std::pair<std::pair<double, double>, std::pair<double, double>> getAvailableMemSwapTotalMemSwap() {
|
||||
double memAvailable = 0, swapFree = 0, memTotal = 0, swapTotal = 0;
|
||||
std::regex memRegex("^(.+):\\s+(\\d+) kB$");
|
||||
std::string line;
|
||||
std::smatch match;
|
||||
std::ifstream meminfo("/proc/meminfo");
|
||||
while (std::getline(meminfo, line)) {
|
||||
if (std::regex_match(line, match, memRegex)) {
|
||||
if ("MemAvailable" == match[1]) {
|
||||
memAvailable = stod(match[2]) / (1024 * 1024);
|
||||
} else if ("SwapFree" == match[1]) {
|
||||
swapFree = stod(match[2]) / (1024 * 1024);
|
||||
} else if ("MemTotal" == match[1]) {
|
||||
memTotal = stod(match[2]) / (1024 * 1024);
|
||||
} else if ("SwapTotal" == match[1]) {
|
||||
swapTotal = stod(match[2]) / (1024 * 1024);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (0 == memTotal) {
|
||||
throw std::runtime_error("Can't get MemTotal");
|
||||
}
|
||||
return {{memAvailable, swapFree}, {memTotal, swapTotal}};
|
||||
}
|
||||
|
||||
double getMemTotal() {
|
||||
return getAvailableMemSwapTotalMemSwap().second.first;
|
||||
}
|
||||
}
|
||||
|
||||
class MemoryMonitor::PerformanceCounter {
|
||||
public:
|
||||
MemState getMemState() {
|
||||
std::pair<std::pair<double, double>, std::pair<double, double>> availableMemSwapTotalMemSwap
|
||||
= getAvailableMemSwapTotalMemSwap();
|
||||
double memTotal = availableMemSwapTotalMemSwap.second.first;
|
||||
double swapTotal = availableMemSwapTotalMemSwap.second.second;
|
||||
return {memTotal, memTotal - availableMemSwapTotalMemSwap.first.first, swapTotal - availableMemSwapTotalMemSwap.first.second};
|
||||
}
|
||||
};
|
||||
|
||||
#else
|
||||
// not implemented
|
||||
namespace {
|
||||
double getMemTotal() {return 0.0;}
|
||||
}
|
||||
|
||||
class MemoryMonitor::PerformanceCounter {
|
||||
public:
|
||||
MemState getMemState() {return {0.0, 0.0, 0.0};}
|
||||
};
|
||||
#endif
|
||||
|
||||
MemoryMonitor::MemoryMonitor() :
|
||||
samplesNumber{0},
|
||||
historySize{0},
|
||||
memSum{0.0},
|
||||
swapSum{0.0},
|
||||
maxMem{0.0},
|
||||
maxSwap{0.0},
|
||||
memTotal{0.0},
|
||||
maxMemTotal{0.0} {}
|
||||
|
||||
// PerformanceCounter is incomplete in header and destructor can't be defined implicitly
|
||||
MemoryMonitor::~MemoryMonitor() = default;
|
||||
|
||||
void MemoryMonitor::setHistorySize(std::size_t size) {
|
||||
if (0 == historySize && 0 != size) {
|
||||
performanceCounter.reset(new MemoryMonitor::PerformanceCounter);
|
||||
// memTotal is not initialized in constructor because for linux its initialization involves constructing
|
||||
// std::regex which is unimplemented and throws an exception for gcc 4.8.5 (default for CentOS 7.4).
|
||||
// Delaying initialization triggers the error only when the monitor is used
|
||||
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53631
|
||||
memTotal = ::getMemTotal();
|
||||
} else if (0 != historySize && 0 == size) {
|
||||
performanceCounter.reset();
|
||||
}
|
||||
historySize = size;
|
||||
std::size_t newSize = min(size, memSwapUsageHistory.size());
|
||||
memSwapUsageHistory.erase(memSwapUsageHistory.begin(), memSwapUsageHistory.end() - newSize);
|
||||
}
|
||||
|
||||
void MemoryMonitor::collectData() {
|
||||
MemState memState = performanceCounter->getMemState();
|
||||
maxMemTotal = max(maxMemTotal, memState.memTotal);
|
||||
memSum += memState.usedMem;
|
||||
swapSum += memState.usedSwap;
|
||||
++samplesNumber;
|
||||
maxMem = max(maxMem, memState.usedMem);
|
||||
maxSwap = max(maxSwap, memState.usedSwap);
|
||||
|
||||
memSwapUsageHistory.emplace_back(memState.usedMem, memState.usedSwap);
|
||||
if (memSwapUsageHistory.size() > historySize) {
|
||||
memSwapUsageHistory.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t MemoryMonitor::getHistorySize() const {
|
||||
return historySize;
|
||||
}
|
||||
|
||||
std::deque<std::pair<double, double>> MemoryMonitor::getLastHistory() const {
|
||||
return memSwapUsageHistory;
|
||||
}
|
||||
|
||||
double MemoryMonitor::getMeanMem() const {
|
||||
return samplesNumber ? memSum / samplesNumber : 0;
|
||||
}
|
||||
|
||||
double MemoryMonitor::getMeanSwap() const {
|
||||
return samplesNumber ? swapSum / samplesNumber : 0;
|
||||
}
|
||||
|
||||
double MemoryMonitor::getMaxMem() const {
|
||||
return maxMem;
|
||||
}
|
||||
|
||||
double MemoryMonitor::getMaxSwap() const {
|
||||
return maxSwap;
|
||||
}
|
||||
|
||||
double MemoryMonitor::getMemTotal() const {
|
||||
return memTotal;
|
||||
}
|
||||
|
||||
double MemoryMonitor::getMaxMemTotal() const {
|
||||
return maxMemTotal;
|
||||
}
|
||||
330
engines/OpenVINOEngine/src/monitors/presenter.cpp
Normal file
330
engines/OpenVINOEngine/src/monitors/presenter.cpp
Normal file
@@ -0,0 +1,330 @@
|
||||
// Copyright (C) 2019-2024 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include <cctype>
|
||||
#include <chrono>
|
||||
#include <iomanip>
|
||||
#include <numeric>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "monitors/presenter.h"
|
||||
|
||||
namespace {
|
||||
const std::map<int, MonitorType> keyToMonitorType{
|
||||
{'C', MonitorType::CpuAverage},
|
||||
{'D', MonitorType::DistributionCpu},
|
||||
{'M', MonitorType::Memory}};
|
||||
|
||||
std::set<MonitorType> strKeysToMonitorSet(const std::string& keys) {
|
||||
std::set<MonitorType> enabledMonitors;
|
||||
if (keys == "h") {
|
||||
return enabledMonitors;
|
||||
}
|
||||
for (unsigned char key: keys) {
|
||||
if (key == 'h') {
|
||||
throw std::runtime_error("Unacceptable combination of monitor types-can't show and hide info at the same time");
|
||||
}
|
||||
auto iter = keyToMonitorType.find(std::toupper(key));
|
||||
if (keyToMonitorType.end() == iter) {
|
||||
throw std::runtime_error("Unknown monitor type");
|
||||
} else {
|
||||
enabledMonitors.insert(iter->second);
|
||||
}
|
||||
}
|
||||
return enabledMonitors;
|
||||
}
|
||||
}
|
||||
|
||||
Presenter::Presenter(std::set<MonitorType> enabledMonitors,
|
||||
int yPos,
|
||||
cv::Size graphSize,
|
||||
std::size_t historySize) :
|
||||
yPos{yPos},
|
||||
graphSize{graphSize},
|
||||
graphPadding{std::max(1, static_cast<int>(graphSize.width * 0.05))},
|
||||
historySize{historySize},
|
||||
distributionCpuEnabled{false},
|
||||
strStream{std::ios_base::app} {
|
||||
for (MonitorType monitor : enabledMonitors) {
|
||||
addRemoveMonitor(monitor);
|
||||
}
|
||||
}
|
||||
|
||||
Presenter::Presenter(const std::string& keys, int yPos, cv::Size graphSize, std::size_t historySize) :
|
||||
Presenter{strKeysToMonitorSet(keys), yPos, graphSize, historySize} {}
|
||||
|
||||
void Presenter::addRemoveMonitor(MonitorType monitor) {
|
||||
unsigned updatedHistorySize = 1;
|
||||
if (historySize > 1) {
|
||||
int sampleStep = std::max(1, static_cast<int>(graphSize.width / (historySize - 1)));
|
||||
// +1 to plot graphSize.width/sampleStep segments
|
||||
// add round up to and an extra element if don't reach graph edge
|
||||
updatedHistorySize = (graphSize.width + sampleStep - 1) / sampleStep + 1;
|
||||
}
|
||||
switch(monitor) {
|
||||
case MonitorType::CpuAverage: {
|
||||
if (cpuMonitor.getHistorySize() > 1 && distributionCpuEnabled) {
|
||||
cpuMonitor.setHistorySize(1);
|
||||
} else if (cpuMonitor.getHistorySize() > 1 && !distributionCpuEnabled) {
|
||||
cpuMonitor.setHistorySize(0);
|
||||
} else { // cpuMonitor.getHistorySize() <= 1
|
||||
cpuMonitor.setHistorySize(updatedHistorySize);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MonitorType::DistributionCpu: {
|
||||
if (distributionCpuEnabled) {
|
||||
distributionCpuEnabled = false;
|
||||
if (1 == cpuMonitor.getHistorySize()) { // cpuMonitor was used only for DistributionCpu => disable it
|
||||
cpuMonitor.setHistorySize(0);
|
||||
}
|
||||
} else {
|
||||
distributionCpuEnabled = true;
|
||||
cpuMonitor.setHistorySize(std::max(std::size_t{1}, cpuMonitor.getHistorySize()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MonitorType::Memory: {
|
||||
if (memoryMonitor.getHistorySize() > 1) {
|
||||
memoryMonitor.setHistorySize(0);
|
||||
} else {
|
||||
memoryMonitor.setHistorySize(updatedHistorySize);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Presenter::handleKey(int key) {
|
||||
key = std::toupper(key);
|
||||
if ('H' == key) {
|
||||
if (0 == cpuMonitor.getHistorySize() && memoryMonitor.getHistorySize() <= 1) {
|
||||
addRemoveMonitor(MonitorType::CpuAverage);
|
||||
addRemoveMonitor(MonitorType::DistributionCpu);
|
||||
addRemoveMonitor(MonitorType::Memory);
|
||||
} else {
|
||||
cpuMonitor.setHistorySize(0);
|
||||
distributionCpuEnabled = false;
|
||||
memoryMonitor.setHistorySize(0);
|
||||
}
|
||||
} else {
|
||||
auto iter = keyToMonitorType.find(key);
|
||||
if (keyToMonitorType.end() != iter) {
|
||||
addRemoveMonitor(iter->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Presenter::drawGraphs(cv::Mat& frame) {
|
||||
const std::chrono::steady_clock::time_point curTimeStamp = std::chrono::steady_clock::now();
|
||||
if (curTimeStamp - prevTimeStamp >= std::chrono::milliseconds{1000}) {
|
||||
prevTimeStamp = curTimeStamp;
|
||||
if (0 != cpuMonitor.getHistorySize()) {
|
||||
cpuMonitor.collectData();
|
||||
}
|
||||
if (memoryMonitor.getHistorySize() > 1) {
|
||||
memoryMonitor.collectData();
|
||||
}
|
||||
}
|
||||
|
||||
int numberOfEnabledMonitors = (cpuMonitor.getHistorySize() > 1) + distributionCpuEnabled
|
||||
+ (memoryMonitor.getHistorySize() > 1);
|
||||
int panelWidth = graphSize.width * numberOfEnabledMonitors
|
||||
+ std::max(0, numberOfEnabledMonitors - 1) * graphPadding;
|
||||
while (panelWidth > frame.cols) {
|
||||
panelWidth = std::max(0, panelWidth - graphSize.width - graphPadding);
|
||||
--numberOfEnabledMonitors; // can't draw all monitors
|
||||
}
|
||||
int graphPos = std::max(0, (frame.cols - 1 - panelWidth) / 2);
|
||||
int textGraphSplittingLine = graphSize.height / 5;
|
||||
int graphRectHeight = graphSize.height - textGraphSplittingLine;
|
||||
int sampleStep = 1;
|
||||
unsigned possibleHistorySize = 1;
|
||||
if (historySize > 1) {
|
||||
sampleStep = std::max(1, static_cast<int>(graphSize.width / (historySize - 1)));
|
||||
possibleHistorySize = (graphSize.width + sampleStep - 1) / sampleStep + 1;
|
||||
}
|
||||
|
||||
if (cpuMonitor.getHistorySize() > 1 && possibleHistorySize > 1 && --numberOfEnabledMonitors >= 0) {
|
||||
std::deque<std::vector<double>> lastHistory = cpuMonitor.getLastHistory();
|
||||
cv::Rect intersection = cv::Rect{cv::Point(graphPos, yPos), graphSize} & cv::Rect{0, 0, frame.cols, frame.rows};
|
||||
if (!intersection.area()) {
|
||||
return;
|
||||
}
|
||||
cv::Mat graph = frame(intersection);
|
||||
graph = graph / 2 + cv::Scalar{127, 127, 127};
|
||||
|
||||
int lineXPos = graph.cols - 1;
|
||||
std::vector<cv::Point> averageLoad(lastHistory.size());
|
||||
|
||||
for (int i = lastHistory.size() - 1; i >= 0; --i) {
|
||||
double mean = std::accumulate(lastHistory[i].begin(), lastHistory[i].end(), 0.0) / lastHistory[i].size();
|
||||
averageLoad[i] = {lineXPos, graphSize.height - static_cast<int>(mean * graphRectHeight)};
|
||||
lineXPos -= sampleStep;
|
||||
}
|
||||
|
||||
cv::polylines(graph, averageLoad, false, {255, 0, 0}, 2);
|
||||
cv::rectangle(frame, cv::Rect{
|
||||
cv::Point{graphPos, yPos + textGraphSplittingLine},
|
||||
cv::Size{graphSize.width, graphSize.height - textGraphSplittingLine}
|
||||
}, {0, 0, 0});
|
||||
strStream.str("CPU");
|
||||
if (!lastHistory.empty()) {
|
||||
strStream << ": " << std::fixed << std::setprecision(1)
|
||||
<< std::accumulate(lastHistory.back().begin(), lastHistory.back().end(), 0.0)
|
||||
/ lastHistory.back().size() * 100 << '%';
|
||||
}
|
||||
int baseline;
|
||||
int textWidth = cv::getTextSize(strStream.str(),
|
||||
cv::FONT_HERSHEY_SIMPLEX,
|
||||
textGraphSplittingLine * 0.04,
|
||||
1,
|
||||
&baseline).width;
|
||||
cv::putText(graph,
|
||||
strStream.str(),
|
||||
cv::Point{(graphSize.width - textWidth) / 2, textGraphSplittingLine - 1},
|
||||
cv::FONT_HERSHEY_SIMPLEX,
|
||||
textGraphSplittingLine * 0.04,
|
||||
{70, 0, 0},
|
||||
1);
|
||||
graphPos += graphSize.width + graphPadding;
|
||||
}
|
||||
|
||||
if (distributionCpuEnabled && --numberOfEnabledMonitors >= 0) {
|
||||
std::deque<std::vector<double>> lastHistory = cpuMonitor.getLastHistory();
|
||||
cv::Rect intersection = cv::Rect{cv::Point(graphPos, yPos), graphSize} & cv::Rect{0, 0, frame.cols, frame.rows};
|
||||
if (!intersection.area()) {
|
||||
return;
|
||||
}
|
||||
cv::Mat graph = frame(intersection);
|
||||
graph = graph / 2 + cv::Scalar{127, 127, 127};
|
||||
|
||||
if (!lastHistory.empty()) {
|
||||
int rectXPos = 0;
|
||||
int step = (graph.cols + lastHistory.back().size() - 1) / lastHistory.back().size(); // round up
|
||||
double sum = 0;
|
||||
for (double coreLoad : lastHistory.back()) {
|
||||
sum += coreLoad;
|
||||
int height = static_cast<int>(graphRectHeight * coreLoad);
|
||||
cv::Rect pillar{cv::Point{rectXPos, graph.rows - height}, cv::Size{step, height}};
|
||||
cv::rectangle(graph, pillar, {255, 0, 0}, cv::FILLED);
|
||||
cv::rectangle(graph, pillar, {0, 0, 0});
|
||||
rectXPos += step;
|
||||
}
|
||||
sum /= lastHistory.back().size();
|
||||
int yLine = graph.rows - static_cast<int>(graphRectHeight * sum);
|
||||
cv::line(graph, cv::Point{0, yLine}, cv::Point{graph.cols, yLine}, {0, 255, 0}, 2);
|
||||
}
|
||||
cv::Rect border{cv::Point{graphPos, yPos + textGraphSplittingLine},
|
||||
cv::Size{graphSize.width, graphSize.height - textGraphSplittingLine}};
|
||||
cv::rectangle(frame, border, {0, 0, 0});
|
||||
strStream.str("Core load");
|
||||
if (!lastHistory.empty()) {
|
||||
strStream << ": " << std::fixed << std::setprecision(1)
|
||||
<< std::accumulate(lastHistory.back().begin(), lastHistory.back().end(), 0.0)
|
||||
/ lastHistory.back().size() * 100 << '%';
|
||||
}
|
||||
int baseline;
|
||||
int textWidth = cv::getTextSize(strStream.str(),
|
||||
cv::FONT_HERSHEY_SIMPLEX,
|
||||
textGraphSplittingLine * 0.04,
|
||||
1,
|
||||
&baseline).width;
|
||||
cv::putText(graph,
|
||||
strStream.str(),
|
||||
cv::Point{(graphSize.width - textWidth) / 2, textGraphSplittingLine - 1},
|
||||
cv::FONT_HERSHEY_SIMPLEX,
|
||||
textGraphSplittingLine * 0.04,
|
||||
{0, 70, 0});
|
||||
graphPos += graphSize.width + graphPadding;
|
||||
}
|
||||
|
||||
if (memoryMonitor.getHistorySize() > 1 && possibleHistorySize > 1 && --numberOfEnabledMonitors >= 0) {
|
||||
std::deque<std::pair<double, double>> lastHistory = memoryMonitor.getLastHistory();
|
||||
cv::Rect intersection = cv::Rect{cv::Point(graphPos, yPos), graphSize} & cv::Rect{0, 0, frame.cols, frame.rows};
|
||||
if (!intersection.area()) {
|
||||
return;
|
||||
}
|
||||
cv::Mat graph = frame(intersection);
|
||||
graph = graph / 2 + cv::Scalar{127, 127, 127};
|
||||
int histxPos = graph.cols - 1;
|
||||
double range = std::min(memoryMonitor.getMaxMemTotal() + memoryMonitor.getMaxSwap(),
|
||||
(memoryMonitor.getMaxMem() + memoryMonitor.getMaxSwap()) * 1.2);
|
||||
if (lastHistory.size() > 1) {
|
||||
for (auto memUsageIt = lastHistory.rbegin(); memUsageIt != lastHistory.rend() - 1; ++memUsageIt) {
|
||||
constexpr double SWAP_THRESHOLD = 10.0 / 1024; // 10 MiB
|
||||
cv::Vec3b color =
|
||||
(memoryMonitor.getMemTotal() * 0.95 > memUsageIt->first) || (memUsageIt->second < SWAP_THRESHOLD) ?
|
||||
cv::Vec3b{0, 255, 255} :
|
||||
cv::Vec3b{0, 0, 255};
|
||||
cv::Point right{histxPos,
|
||||
graph.rows - static_cast<int>(graphRectHeight * (memUsageIt->first + memUsageIt->second) / range)};
|
||||
cv::Point left{histxPos - sampleStep,
|
||||
graph.rows - static_cast<int>(
|
||||
graphRectHeight * ((memUsageIt + 1)->first + (memUsageIt + 1)->second) / range)};
|
||||
cv::line(graph, right, left, color, 2);
|
||||
histxPos -= sampleStep;
|
||||
}
|
||||
}
|
||||
|
||||
cv::Rect border{cv::Point{graphPos, yPos + textGraphSplittingLine},
|
||||
cv::Size{graphSize.width, graphSize.height - textGraphSplittingLine}};
|
||||
cv::rectangle(frame, {border}, {0, 0, 0});
|
||||
if (lastHistory.empty()) {
|
||||
strStream.str("Memory");
|
||||
} else {
|
||||
strStream.str("");
|
||||
strStream << std::fixed << std::setprecision(1) << lastHistory.back().first << " + "
|
||||
<< lastHistory.back().second << " GiB";
|
||||
}
|
||||
int baseline;
|
||||
int textWidth = cv::getTextSize(strStream.str(),
|
||||
cv::FONT_HERSHEY_SIMPLEX,
|
||||
textGraphSplittingLine * 0.04,
|
||||
1,
|
||||
&baseline).width;
|
||||
cv::putText(graph,
|
||||
strStream.str(),
|
||||
cv::Point{(graphSize.width - textWidth) / 2, textGraphSplittingLine - 1},
|
||||
cv::FONT_HERSHEY_SIMPLEX,
|
||||
textGraphSplittingLine * 0.04,
|
||||
{0, 35, 35});
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> Presenter::reportMeans() const {
|
||||
std::vector<std::string> collectedData;
|
||||
if (cpuMonitor.getHistorySize() > 1 || distributionCpuEnabled || memoryMonitor.getHistorySize() > 1) {
|
||||
collectedData.push_back("Resources usage:");
|
||||
}
|
||||
if (cpuMonitor.getHistorySize() > 1) {
|
||||
std::ostringstream collectedDataStream;
|
||||
collectedDataStream << std::fixed << std::setprecision(1);
|
||||
collectedDataStream << "\tMean core utilization: ";
|
||||
for (double mean : cpuMonitor.getMeanCpuLoad()) {
|
||||
collectedDataStream << mean * 100 << "% ";
|
||||
}
|
||||
collectedData.push_back(collectedDataStream.str());
|
||||
}
|
||||
if (distributionCpuEnabled) {
|
||||
std::ostringstream collectedDataStream;
|
||||
collectedDataStream << std::fixed << std::setprecision(1);
|
||||
std::vector<double> meanCpuLoad = cpuMonitor.getMeanCpuLoad();
|
||||
double mean = std::accumulate(meanCpuLoad.begin(), meanCpuLoad.end(), 0.0) / meanCpuLoad.size();
|
||||
collectedDataStream << "\tMean CPU utilization: " << mean * 100 << "%";
|
||||
collectedData.push_back(collectedDataStream.str());
|
||||
}
|
||||
if (memoryMonitor.getHistorySize() > 1) {
|
||||
std::ostringstream collectedDataStream;
|
||||
collectedDataStream << std::fixed << std::setprecision(1);
|
||||
collectedDataStream << "\tMemory mean usage: " << memoryMonitor.getMeanMem() << " GiB";
|
||||
collectedData.push_back(collectedDataStream.str());
|
||||
collectedDataStream.str("");
|
||||
collectedDataStream << "\tMean swap usage: " << memoryMonitor.getMeanSwap() << " GiB";
|
||||
collectedData.push_back(collectedDataStream.str());
|
||||
}
|
||||
|
||||
return collectedData;
|
||||
}
|
||||
22
engines/OpenVINOEngine/src/monitors/query_wrapper.cpp
Normal file
22
engines/OpenVINOEngine/src/monitors/query_wrapper.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright (C) 2019-2024 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "query_wrapper.h"
|
||||
|
||||
#include <Windows.h>
|
||||
#include <system_error>
|
||||
|
||||
QueryWrapper::QueryWrapper() {
|
||||
PDH_STATUS status = PdhOpenQuery(NULL, NULL, &query);
|
||||
if (ERROR_SUCCESS != status) {
|
||||
throw std::system_error(status, std::system_category(), "PdhOpenQuery() failed");
|
||||
}
|
||||
}
|
||||
QueryWrapper::~QueryWrapper() {
|
||||
PdhCloseQuery(query);
|
||||
}
|
||||
|
||||
QueryWrapper::operator PDH_HQUERY() const {
|
||||
return query;
|
||||
}
|
||||
17
engines/OpenVINOEngine/src/monitors/query_wrapper.h
Normal file
17
engines/OpenVINOEngine/src/monitors/query_wrapper.h
Normal file
@@ -0,0 +1,17 @@
|
||||
// Copyright (C) 2019-2024 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Pdh.h>
|
||||
class QueryWrapper {
|
||||
public:
|
||||
QueryWrapper();
|
||||
~QueryWrapper();
|
||||
QueryWrapper(const QueryWrapper&) = delete;
|
||||
QueryWrapper& operator=(const QueryWrapper&) = delete;
|
||||
operator PDH_HQUERY() const;
|
||||
private:
|
||||
PDH_HQUERY query;
|
||||
};
|
||||
Reference in New Issue
Block a user