#3045 Implement memory display in status bar of the main window

This commit is contained in:
Gaute Lindkvist
2018-06-14 12:04:16 +02:00
parent 9cf4938651
commit 2f0b1cfdb9
5 changed files with 269 additions and 8 deletions

View File

@@ -61,6 +61,7 @@
#include "cafAnimationToolBar.h"
#include "cafCmdExecCommandManager.h"
#include "cafCmdFeatureManager.h"
#include "cafMemoryInspector.h"
#include "cafPdmSettings.h"
#include "cafPdmUiPropertyView.h"
#include "cafPdmUiPropertyViewDialog.h"
@@ -85,10 +86,13 @@
#include <QMenuBar>
#include <QSpinBox>
#include <QStatusBar>
#include <QTimer>
#include <QToolBar>
#include <QTreeView>
#include <QUndoStack>
#include <algorithm>
//==================================================================================================
///
@@ -140,14 +144,19 @@ RiuMainWindow::RiuMainWindow()
// When enableUndoCommandSystem is set false, all commands are executed and deleted immediately
//caf::CmdExecCommandManager::instance()->enableUndoCommandSystem(true);
QLabel* memoryDescriptionLabel = new QLabel("Memory usage:");
m_memoryUsedStatus = new QLabel("Used: 128 MiB");
m_memoryUsedStatus->setStyleSheet("QLabel {color: green; }");
m_memoryAvailableStatus = new QLabel("Physical Memory: 32 GiB");
statusBar()->addPermanentWidget(memoryDescriptionLabel);
m_memoryCriticalWarning = new QLabel("");
m_memoryUsedStatus = new QLabel("");
m_memoryTotalStatus = new QLabel("");
statusBar()->addPermanentWidget(m_memoryCriticalWarning);
statusBar()->addPermanentWidget(m_memoryUsedStatus);
statusBar()->addPermanentWidget(m_memoryAvailableStatus);
statusBar()->addPermanentWidget(m_memoryTotalStatus);
updateMemoryUsage();
m_memoryRefreshTimer = new QTimer(this);
connect(m_memoryRefreshTimer, SIGNAL(timeout()), this, SLOT(updateMemoryUsage()));
m_memoryRefreshTimer->start(1000);
}
@@ -1683,6 +1692,53 @@ void RiuMainWindow::updateUiFieldsFromActiveResult(caf::PdmObjectHandle* objectT
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuMainWindow::updateMemoryUsage()
{
uint64_t currentUsage = caf::MemoryInspector::getApplicationPhysicalMemoryUsageMiB();
uint64_t totalPhysicalMemory = caf::MemoryInspector::getTotalPhysicalMemoryMiB();
uint64_t totalVirtualMemory = caf::MemoryInspector::getTotalVirtualMemoryMiB();
uint64_t availVirtualMemory = caf::MemoryInspector::getAvailableVirtualMemoryMiB();
QColor okColor(0, 150, 0);
QColor warningColor(200, 0, 0);
QColor criticalColor(255, 100, 0);
float currentUsageFraction = 0.0f;
float availVirtualFraction = 1.0f;
if (currentUsage > 0u && totalPhysicalMemory > 0u)
{
currentUsageFraction = std::min(1.0f, static_cast<float>(currentUsage) / totalPhysicalMemory);
}
if (availVirtualMemory > 0u && totalVirtualMemory > 0u)
{
availVirtualFraction = static_cast<float>(availVirtualMemory) / totalVirtualMemory;
}
QColor usageColor((int)(okColor.red() * (1.0 - currentUsageFraction) + warningColor.red() * currentUsageFraction),
(int)(okColor.green() * (1.0 - currentUsageFraction) + warningColor.green() * currentUsageFraction),
(int)(okColor.blue() * (1.0 - currentUsageFraction) + warningColor.blue() * currentUsageFraction));
m_memoryCriticalWarning->setText(QString(""));
if (availVirtualFraction < 0.175)
{
m_memoryCriticalWarning->setText(QString("Available System Memory Critically Low!"));
m_memoryCriticalWarning->setStyleSheet(QString("QLabel {color: %1; padding: 0px 5px 0px 0px;}").arg(criticalColor.name()));
}
else
{
m_memoryCriticalWarning->setText(QString(""));
}
m_memoryUsedStatus->setText(QString("Physical Memory Used: %1 MiB").arg(currentUsage));
m_memoryTotalStatus->setText(QString("Total Physical Memory: %1 MiB").arg(totalPhysicalMemory));
m_memoryUsedStatus->setStyleSheet(QString("QLabel {color: %1; padding: 0px 5px 0px 0px;}").arg(usageColor.name()));
m_memoryTotalStatus->setStyleSheet(QString("QLabel {padding: 0px 5px 0px 0px; }"));
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -36,6 +36,7 @@
class QActionGroup;
class QMdiSubWindow;
class QSpinBox;
class QTimer;
class QUndoView;
class RimCase;
@@ -181,14 +182,19 @@ private:
RiuPvtPlotPanel* m_pvtPlotPanel;
QMenu* m_windowMenu;
QLabel* m_memoryCriticalWarning;
QLabel* m_memoryUsedStatus;
QLabel* m_memoryAvailableStatus;
QLabel* m_memoryTotalStatus;
QTimer* m_memoryRefreshTimer;
// Menu and action slots
private slots:
friend class RiuMdiSubWindow;
// Memory update slot
void updateMemoryUsage();
// File slots
void slotRefreshFileActions();

View File

@@ -42,6 +42,9 @@ add_library( ${PROJECT_NAME}
cafVecIjk.cpp
cafVecIjk.h
cafMemoryInspector.cpp
cafMemoryInspector.h
${MOC_FILES_CPP}
)

View File

@@ -0,0 +1,145 @@
#include "cafMemoryInspector.h"
#include <QFile>
#include <QRegExp>
#include <QString>
#include <QStringList>
#ifdef _WIN32
#include "windows.h"
#include "psapi.h"
#elif defined (__linux__)
#include <map>
#include <unistd.h>
#include "sys/types.h"
#include "sys/sysinfo.h"
#endif
#define MIB_DIV 1048576
#ifdef __linux__
//--------------------------------------------------------------------------------------------------
/// Read bytes of memory of different types for current process from /proc/self/statm
/// See: http://man7.org/linux/man-pages/man5/proc.5.html
/// The first three columns in statm are:
/// * VmSize: size of virtual memory
/// * RSS: resident memory size of process
/// * Shared: shared memory used by process
//--------------------------------------------------------------------------------------------------
std::map<QString, uint64_t> readProcessBytesLinux()
{
std::map<QString, uint64_t> quantities;
int pageSize = getpagesize();
QFile procSelfStatus("/proc/self/statm");
if (procSelfStatus.open(QIODevice::ReadOnly | QIODevice::Text))
{
QString line(procSelfStatus.readLine(256));
QStringList lineWords = line.split(QRegExp("\\s+"), QString::SkipEmptyParts);
quantities["VmSize"] = static_cast<uint64_t>(lineWords[0].toLongLong() * pageSize);
quantities["RSS"] = static_cast<uint64_t>(lineWords[1].toLongLong() * pageSize);
quantities["Shared"] = static_cast<uint64_t>(lineWords[2].toLongLong() * pageSize);
}
return quantities;
}
#endif
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
uint64_t caf::MemoryInspector::getApplicationPhysicalMemoryUsageMiB()
{
#ifdef _WIN32
PROCESS_MEMORY_COUNTERS_EX pmc;
GetProcessMemoryInfo(GetCurrentProcess(), (PPROCESS_MEMORY_COUNTERS) &pmc, sizeof(pmc));
SIZE_T physicalMemUsedByMe = pmc.WorkingSetSize;
return static_cast<uint64_t>(physicalMemUsedByMe / MIB_DIV);
#elif defined(__linux__)
return readProcessBytesLinux()["RSS"] / MIB_DIV;
#else
return 0u;
#endif
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
uint64_t caf::MemoryInspector::getApplicationVirtualMemoryUsageMiB()
{
#ifdef _WIN32
PROCESS_MEMORY_COUNTERS_EX pmc;
GetProcessMemoryInfo(GetCurrentProcess(), (PPROCESS_MEMORY_COUNTERS)&pmc, sizeof(pmc));
SIZE_T virtualMemUsedByMe = pmc.PrivateUsage;
return static_cast<uint64_t>(virtualMemUsedByMe / MIB_DIV);
#elif defined(__linux__)
return readProcessBytesLinux()["VmSize"] / MIB_DIV;
#else
return 0u;
#endif
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
uint64_t caf::MemoryInspector::getTotalVirtualMemoryMiB()
{
#ifdef _WIN32
MEMORYSTATUSEX memInfo;
memInfo.dwLength = sizeof(MEMORYSTATUSEX);
GlobalMemoryStatusEx(&memInfo);
DWORDLONG totalVirtualMem = memInfo.ullTotalPageFile;
return static_cast<uint64_t> (totalVirtualMem / MIB_DIV);
#elif defined(__linux__)
struct sysinfo memInfo;
sysinfo(&memInfo);
long long totalVirtualMem = memInfo.totalram;
totalVirtualMem += memInfo.totalswap;
totalVirtualMem *= memInfo.mem_unit;
return totalVirtualMem / MIB_DIV;
#else
return 0u;
#endif
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
uint64_t caf::MemoryInspector::getTotalPhysicalMemoryMiB()
{
#ifdef _WIN32
MEMORYSTATUSEX memInfo;
memInfo.dwLength = sizeof(MEMORYSTATUSEX);
GlobalMemoryStatusEx(&memInfo);
DWORDLONG totalPhysMem = memInfo.ullTotalPhys;
return static_cast<uint64_t>(totalPhysMem / MIB_DIV);
#elif defined(__linux__)
struct sysinfo memInfo;
sysinfo(&memInfo);
long long totalPhysicalMem = memInfo.totalram;
totalPhysicalMem *= memInfo.mem_unit;
return totalPhysicalMem / MIB_DIV;
#else
return 0u;
#endif
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
uint64_t caf::MemoryInspector::getAvailableVirtualMemoryMiB()
{
#ifdef _WIN32
MEMORYSTATUSEX memInfo;
memInfo.dwLength = sizeof(MEMORYSTATUSEX);
GlobalMemoryStatusEx(&memInfo);
DWORDLONG availVirtualMem = memInfo.ullAvailPageFile;
return static_cast<uint64_t> (availVirtualMem / MIB_DIV);
#elif defined(__linux__)
struct sysinfo memInfo;
sysinfo(&memInfo);
long long availVirtualMem = memInfo.freeram;
availVirtualMem += memInfo.freeswap;
availVirtualMem *= memInfo.mem_unit;
return availVirtualMem / MIB_DIV;
#else
return 0u;
#endif
}

View File

@@ -0,0 +1,51 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2018- Ceetron AS
//
// This library may be used under the terms of either the GNU General Public License or
// the GNU Lesser General Public License as follows:
//
// GNU General Public License Usage
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
// GNU Lesser General Public License Usage
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include <cstdint>
namespace caf
{
namespace MemoryInspector
{
uint64_t getApplicationPhysicalMemoryUsageMiB();
uint64_t getApplicationVirtualMemoryUsageMiB();
uint64_t getTotalVirtualMemoryMiB();
uint64_t getTotalPhysicalMemoryMiB();
uint64_t getAvailableVirtualMemoryMiB();
}
}