Show resource usage in UI

This commit is contained in:
Martchus 2022-04-23 19:39:31 +02:00
parent 6965d9b40b
commit 142f6466ae
9 changed files with 128 additions and 8 deletions

View File

@ -62,6 +62,11 @@ void Config::initStorage(const char *path, std::uint32_t maxDbs)
aur.initStorage(*m_storage);
}
std::size_t Config::cachedPackages() const
{
return m_storage ? m_storage->packageCache().size() : 0;
}
void Config::setPackageCacheLimit(std::size_t limit)
{
m_storage->packageCache().setLimit(limit);

View File

@ -121,6 +121,7 @@ struct LIBPKG_EXPORT Config : public Lockable, public ReflectiveRapidJSON::Binar
// storage and caching
void initStorage(const char *path = "libpkg.db", std::uint32_t maxDbs = 0);
std::size_t cachedPackages() const;
void setPackageCacheLimit(std::size_t limit);
std::unique_ptr<StorageDistribution> &storage();
std::uint64_t restoreFromCache();

View File

@ -102,6 +102,7 @@ public:
iterator begin();
iterator end();
void setLimit(std::size_t limit);
std::size_t size() const;
private:
EntryList m_entries;
@ -129,6 +130,11 @@ template <typename StorageEntryType> inline auto StorageCacheEntries<StorageEntr
return m_entries.end();
}
template <typename StorageEntryType> inline std::size_t StorageCacheEntries<StorageEntryType>::size() const
{
return m_entries.size();
}
template <typename StorageEntriesType, typename StorageType, typename SpecType> struct StorageCache {
using Entries = StorageEntriesType;
using Entry = typename Entries::Entry;
@ -151,12 +157,19 @@ template <typename StorageEntriesType, typename StorageType, typename SpecType>
void clear(Storage &storage);
void clearCacheOnly(Storage &storage);
void setLimit(std::size_t limit);
std::size_t size();
private:
Entries m_entries;
std::mutex m_mutex;
};
template <typename StorageEntriesType, typename StorageType, typename SpecType>
std::size_t StorageCache<StorageEntriesType, StorageType, SpecType>::size()
{
return m_entries.size();
}
} // namespace LibPkg
#endif // LIBPKG_DATA_STORAGE_GENERIC_H

View File

@ -4,6 +4,7 @@ cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR)
set(HEADER_FILES
errorhandling.h
serversetup.h
resourceusage.h
helper.h
json.h
logcontext.h
@ -32,6 +33,7 @@ set(SRC_FILES
json.cpp
errorhandling.cpp
serversetup.cpp
resourceusage.cpp
globallock.cpp
authentication.cpp
webapi/server.cpp
@ -128,6 +130,7 @@ add_reflection_generator_invocation(
INPUT_FILES
errorhandling.h
serversetup.h
resourceusage.h
buildactions/buildaction.h
buildactions/buildactionmeta.h
buildactions/buildactiontemplate.h

View File

@ -0,0 +1,40 @@
#include "./resourceusage.h"
#if defined(PLATFORM_WINDOWS)
#include <psapi.h>
#include <windows.h>
#elif defined(PLATFORM_LINUX) || defined(PLATFORM_UNIX)
#include <cstdio>
#include <sys/resource.h>
#include <unistd.h>
#endif
namespace LibRepoMgr {
ResourceUsage::ResourceUsage()
{
#if defined(PLATFORM_WINDOWS)
auto info = PROCESS_MEMORY_COUNTERS();
GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info));
physicalMemory = static_cast<std::size_t>(info.WorkingSetSize);
physicalMemoryPeak = static_cast<std::size_t>(info.PeakWorkingSetSize);
#elif defined(PLATFORM_LINUX) || defined(PLATFORM_UNIX)
if (auto *const statm = std::fopen("/proc/self/statm", "r")) {
auto pages = 0l, pagesInRealMemory = 0l, pagesShared = 0l;
if (std::fscanf(statm, "%ld%ld%ld", &pages, &pagesInRealMemory, &pagesShared) == 3) {
const auto pageSize = static_cast<std::size_t>(sysconf(_SC_PAGESIZE));
virtualMemory = static_cast<std::size_t>(pages) * pageSize;
residentSetSize = static_cast<std::size_t>(pagesInRealMemory) * pageSize;
sharedResidentSetSize = static_cast<std::size_t>(pagesShared) * pageSize;
}
std::fclose(statm);
}
struct rusage rusage;
getrusage(RUSAGE_SELF, &rusage);
peakResidentSetSize = static_cast<std::size_t>(rusage.ru_maxrss) * 1024u;
#endif
}
} // namespace LibRepoMgr
#include "reflection/resourceusage.h"

View File

@ -0,0 +1,26 @@
#ifndef LIBREPOMGR_RESOURCE_USAGE_H
#define LIBREPOMGR_RESOURCE_USAGE_H
#include "./global.h"
#include <reflective_rapidjson/json/serializable.h>
namespace LibRepoMgr {
struct LIBREPOMGR_EXPORT ResourceUsage : public ReflectiveRapidJSON::JsonSerializable<ResourceUsage> {
explicit ResourceUsage();
std::size_t virtualMemory = 0;
std::size_t residentSetSize = 0;
std::size_t sharedResidentSetSize = 0;
std::size_t peakResidentSetSize = 0;
std::size_t packageDbSize = 0;
std::size_t actionsDbSize = 0;
std::size_t cachedPackages = 0;
std::size_t actionsCount = 0;
std::size_t runningActionsCount = 0;
};
} // namespace LibRepoMgr
#endif // LIBREPOMGR_RESOURCE_USAGE_H

View File

@ -869,12 +869,18 @@ std::string ServiceSetup::Locks::forDatabase(const LibPkg::Database &db)
return forDatabase(db.name, db.arch);
}
ServiceStatus::ServiceStatus(const ServiceSetup &setup)
ServiceStatus::ServiceStatus(ServiceSetup &setup)
: version(applicationInfo.version)
, config(setup.config.computeStatus())
, actions(setup.building.metaInfo)
, presets(setup.building.presets)
{
auto ec = std::error_code();
resourceUsage.packageDbSize = std::filesystem::file_size(setup.dbPath, ec);
resourceUsage.actionsDbSize = std::filesystem::file_size(setup.building.dbPath, ec);
resourceUsage.cachedPackages = setup.config.cachedPackages();
resourceUsage.actionsCount = setup.building.buildActionCount();
resourceUsage.runningActionsCount = setup.building.runningBuildActionCount();
}
} // namespace LibRepoMgr

View File

@ -5,6 +5,7 @@
#include "./buildactions/buildaction.h"
#include "./buildactions/buildactiontemplate.h"
#include "./globallock.h"
#include "./resourceusage.h"
#include "../libpkg/data/config.h"
#include "../libpkg/data/lockable.h"
@ -57,7 +58,7 @@ struct LIBREPOMGR_EXPORT ServiceSetup : public LibPkg::Lockable {
void initStorage();
int run();
int fixDb();
ServiceStatus computeStatus() const;
ServiceStatus computeStatus();
// variables relevant for the web server; only changed when (re)loading config
struct LIBREPOMGR_EXPORT WebServerSetup {
@ -142,7 +143,7 @@ struct LIBREPOMGR_EXPORT ServiceSetup : public LibPkg::Lockable {
LibPkg::StorageID storeBuildAction(const std::shared_ptr<BuildAction> &buildAction);
void deleteBuildAction(const std::vector<std::shared_ptr<BuildAction>> &actions);
std::size_t buildActionCount();
std::size_t runningBuildActionCount();
std::size_t runningBuildActionCount() const;
void rebuildDb();
void forEachBuildAction(std::function<void(std::size_t)> count, std::function<bool(LibPkg::StorageID, BuildAction &&)> &&func,
std::size_t limit, std::size_t start);
@ -185,7 +186,7 @@ inline bool ServiceSetup::BuildSetup::hasStorage() const
return m_storage != nullptr;
}
inline std::size_t ServiceSetup::BuildSetup::runningBuildActionCount()
inline std::size_t ServiceSetup::BuildSetup::runningBuildActionCount() const
{
return m_runningActions.size();
}
@ -214,15 +215,16 @@ inline std::pair<ServiceSetup::Locks::LockTable *, std::unique_lock<std::shared_
}
struct LIBREPOMGR_EXPORT ServiceStatus : public ReflectiveRapidJSON::JsonSerializable<ServiceStatus> {
ServiceStatus(const ServiceSetup &setup);
ServiceStatus(ServiceSetup &setup);
const char *const version = nullptr;
const LibPkg::Status config;
const BuildActionMetaInfo &actions;
const BuildPresets &presets;
ResourceUsage resourceUsage;
};
inline ServiceStatus ServiceSetup::computeStatus() const
inline ServiceStatus ServiceSetup::computeStatus()
{
return ServiceStatus(*this);
}

View File

@ -30,7 +30,7 @@ function handleGlobalStatusUpdate(ajaxRequest)
Utils.getAndEmptyElement('application-version').appendChild(document.createTextNode(applicationVersion));
}
const dbStats = responseJson.config.dbStats;
const table = GenericRendering.renderTableFromJsonArray({
const dbTable = GenericRendering.renderTableFromJsonArray({
rows: dbStats,
columnHeaders: ['Arch', 'Database', 'Package count', 'Last update', 'Synced from mirror'],
columnAccessors: ['arch', 'name', 'packageCount', 'lastUpdate', 'syncFromMirror'],
@ -49,7 +49,31 @@ function handleGlobalStatusUpdate(ajaxRequest)
},
},
});
globalStatus.appendChild(table);
globalStatus.appendChild(dbTable);
const resourceUsageHeading = document.createElement('h2');
resourceUsageHeading.appendChild(document.createTextNode('Resource usage'));
globalStatus.appendChild(resourceUsageHeading);
const resTable = GenericRendering.renderTableFromJsonObject({
data: responseJson.resourceUsage,
displayLabels: [
'Virtual memory', 'Resident set size', 'Peak resident set size', 'Shared resident set size',
'Package-DB size', 'Actions-DB size', 'Cached packages', 'Actions', 'Running actions',
],
fieldAccessors: [
'virtualMemory', 'residentSetSize', 'peakResidentSetSize', 'sharedResidentSetSize',
'packageDbSize', 'actionsDbSize', 'cachedPackages', 'actionsCount', 'runningActionsCount',
],
customRenderer: {
virtualMemory: GenericRendering.renderDataSize,
residentSetSize: GenericRendering.renderDataSize,
peakResidentSetSize: GenericRendering.renderDataSize,
sharedResidentSetSize: GenericRendering.renderDataSize,
packageDbSize: GenericRendering.renderDataSize,
actionsDbSize: GenericRendering.renderDataSize,
},
});
globalStatus.appendChild(resTable);
// update database selections
const repoSelections = [