mirror of
https://github.com/ProjectSkyfire/SkyFire_548
synced 2026-08-18 06:32:13 -04:00
Core/Command: Show system memory in server info
sample result : Memory Summary: Process: RSS 3.76 GB, Private 3.90 GB, Peak RSS 3.76 GB | System: RAM 32.6% (20.83 GB/63.83 GB)
This commit is contained in:
parent
adfe27d1be
commit
91facd3a20
4 changed files with 266 additions and 5 deletions
|
|
@ -137,5 +137,5 @@ sf_add_msvc_cxx_compile_option(/Zm50)
|
|||
sf_add_msvc_cxx_compile_option(/we4263)
|
||||
sf_add_msvc_cxx_compile_option(/we4264)
|
||||
|
||||
set(CMAKE_CXX_STANDARD_LIBRARIES "ws2_32.lib iphlpapi.lib netapi32.lib mswsock.lib psapi.lib kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib")
|
||||
set(CMAKE_C_STANDARD_LIBRARIES "ws2_32.lib iphlpapi.lib netapi32.lib mswsock.lib psapi.lib kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib")
|
||||
set(CMAKE_CXX_STANDARD_LIBRARIES "ws2_32.lib iphlpapi.lib netapi32.lib mswsock.lib psapi.lib sysinfoapi.lib kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib")
|
||||
set(CMAKE_C_STANDARD_LIBRARIES "ws2_32.lib iphlpapi.lib netapi32.lib mswsock.lib psapi.lib sysinfoapi.lib kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib")
|
||||
|
|
|
|||
|
|
@ -137,7 +137,10 @@ public:
|
|||
uint32 maxQueuedClientsNum = sWorld->GetMaxQueuedSessionCount();
|
||||
std::string uptime = secsToTimeString(sWorld->GetUptime());
|
||||
uint32 updateTime = sWorld->GetUpdateTime();
|
||||
Skyfire::ProcessMemoryUsage memoryUsage;
|
||||
Skyfire::ProcessMemoryUsage processMemory;
|
||||
Skyfire::GetProcessMemoryUsage(processMemory);
|
||||
Skyfire::SystemMemoryUsage systemMemory;
|
||||
Skyfire::GetSystemMemoryUsage(systemMemory);
|
||||
|
||||
handler->PSendSysMessage("Open Source Emulation https://www.projectskyfire.org");
|
||||
handler->PSendSysMessage("www.github.com/ProjectSkyfire/SkyFire_548");
|
||||
|
|
@ -145,8 +148,8 @@ public:
|
|||
handler->PSendSysMessage(LANG_CONNECTED_PLAYERS, playersNum, maxPlayersNum);
|
||||
handler->PSendSysMessage(LANG_CONNECTED_USERS, activeClientsNum, maxActiveClientsNum, queuedClientsNum, maxQueuedClientsNum);
|
||||
handler->PSendSysMessage(LANG_UPTIME, uptime.c_str());
|
||||
std::string memoryInfo = Skyfire::GetProcessMemoryUsage(memoryUsage) ? Skyfire::FormatProcessMemoryUsage(memoryUsage) : "unavailable";
|
||||
handler->PSendSysMessage("Memory: %s", memoryInfo.c_str());
|
||||
std::string summary = Skyfire::FormatMemoryUsageSummary(processMemory, systemMemory);
|
||||
handler->PSendSysMessage("Memory Summary: %s", summary.c_str());
|
||||
SendRuntimeMetrics(handler);
|
||||
handler->PSendSysMessage(LANG_UPDATE_DIFF, updateTime);
|
||||
|
||||
|
|
|
|||
|
|
@ -13,12 +13,19 @@
|
|||
#if PLATFORM == PLATFORM_WINDOWS
|
||||
#include <windows.h>
|
||||
#include <psapi.h>
|
||||
#include <sysinfoapi.h>
|
||||
#elif PLATFORM == PLATFORM_UNIX || PLATFORM == PLATFORM_APPLE
|
||||
#include <sys/resource.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if PLATFORM == PLATFORM_UNIX
|
||||
#include <fstream>
|
||||
#include <sys/sysinfo.h>
|
||||
#endif
|
||||
|
||||
#if PLATFORM == PLATFORM_APPLE
|
||||
#include <mach/mach.h>
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
|
@ -30,6 +37,13 @@ namespace
|
|||
stream << label << ' ' << Skyfire::FormatMemorySize(bytes);
|
||||
fields.push_back(stream.str());
|
||||
}
|
||||
|
||||
void AppendPercentageField(std::vector<std::string>& fields, char const* label, double percent)
|
||||
{
|
||||
std::ostringstream stream;
|
||||
stream << label << ' ' << std::fixed << std::setprecision(1) << percent << '%';
|
||||
fields.push_back(stream.str());
|
||||
}
|
||||
}
|
||||
|
||||
bool Skyfire::GetProcessMemoryUsage(ProcessMemoryUsage& usage)
|
||||
|
|
@ -91,6 +105,163 @@ bool Skyfire::GetProcessMemoryUsage(ProcessMemoryUsage& usage)
|
|||
#endif
|
||||
}
|
||||
|
||||
bool Skyfire::GetSystemMemoryUsage(SystemMemoryUsage& usage)
|
||||
{
|
||||
usage = SystemMemoryUsage();
|
||||
|
||||
#if PLATFORM == PLATFORM_WINDOWS
|
||||
MEMORYSTATUSEX memoryStatus;
|
||||
memoryStatus.dwLength = sizeof(memoryStatus);
|
||||
|
||||
if (!GlobalMemoryStatusEx(&memoryStatus))
|
||||
return false;
|
||||
|
||||
usage.totalPhysicalBytes = memoryStatus.ullTotalPhys;
|
||||
usage.availablePhysicalBytes = memoryStatus.ullAvailPhys;
|
||||
usage.usedPhysicalBytes = memoryStatus.ullTotalPhys - memoryStatus.ullAvailPhys;
|
||||
usage.totalVirtualBytes = memoryStatus.ullTotalPageFile;
|
||||
usage.usedVirtualBytes = memoryStatus.ullTotalPageFile - memoryStatus.ullAvailPageFile;
|
||||
usage.totalSwapBytes = 0;
|
||||
usage.usedSwapBytes = 0;
|
||||
|
||||
if (usage.totalPhysicalBytes > 0)
|
||||
{
|
||||
usage.physicalUsagePercent = (static_cast<double>(usage.usedPhysicalBytes) /
|
||||
static_cast<double>(usage.totalPhysicalBytes)) * 100.0;
|
||||
}
|
||||
|
||||
if (usage.totalVirtualBytes > 0)
|
||||
{
|
||||
usage.virtualUsagePercent = (static_cast<double>(usage.usedVirtualBytes) /
|
||||
static_cast<double>(usage.totalVirtualBytes)) * 100.0;
|
||||
}
|
||||
|
||||
usage.hasValidData = true;
|
||||
return true;
|
||||
|
||||
#elif PLATFORM == PLATFORM_UNIX
|
||||
std::ifstream meminfo("/proc/meminfo");
|
||||
if (!meminfo.is_open())
|
||||
return false;
|
||||
|
||||
std::string key;
|
||||
uint64 value;
|
||||
std::string unit;
|
||||
uint64 memTotal = 0, memAvailable = 0, swapTotal = 0, swapFree = 0;
|
||||
|
||||
while (meminfo >> key >> value >> unit)
|
||||
{
|
||||
if (key == "MemTotal:")
|
||||
memTotal = value * 1024;
|
||||
else if (key == "MemAvailable:")
|
||||
memAvailable = value * 1024;
|
||||
else if (key == "SwapTotal:")
|
||||
swapTotal = value * 1024;
|
||||
else if (key == "SwapFree:")
|
||||
swapFree = value * 1024;
|
||||
}
|
||||
|
||||
if (memTotal == 0)
|
||||
return false;
|
||||
|
||||
usage.totalPhysicalBytes = memTotal;
|
||||
usage.availablePhysicalBytes = memAvailable > 0 ? memAvailable : 0;
|
||||
usage.usedPhysicalBytes = memTotal - (memAvailable > 0 ? memAvailable : 0);
|
||||
usage.totalSwapBytes = swapTotal;
|
||||
usage.usedSwapBytes = swapTotal - swapFree;
|
||||
usage.totalVirtualBytes = memTotal + swapTotal;
|
||||
usage.usedVirtualBytes = usage.usedPhysicalBytes + usage.usedSwapBytes;
|
||||
|
||||
if (usage.totalPhysicalBytes > 0)
|
||||
{
|
||||
usage.physicalUsagePercent = (static_cast<double>(usage.usedPhysicalBytes) /
|
||||
static_cast<double>(usage.totalPhysicalBytes)) * 100.0;
|
||||
}
|
||||
|
||||
if (usage.totalVirtualBytes > 0)
|
||||
{
|
||||
usage.virtualUsagePercent = (static_cast<double>(usage.usedVirtualBytes) /
|
||||
static_cast<double>(usage.totalVirtualBytes)) * 100.0;
|
||||
}
|
||||
|
||||
usage.hasValidData = true;
|
||||
return true;
|
||||
|
||||
#elif PLATFORM == PLATFORM_APPLE
|
||||
int mib[2];
|
||||
size_t length;
|
||||
|
||||
mib[0] = CTL_HW;
|
||||
mib[1] = HW_MEMSIZE;
|
||||
length = sizeof(uint64_t);
|
||||
if (sysctl(mib, 2, &usage.totalPhysicalBytes, &length, nullptr, 0) != 0)
|
||||
return false;
|
||||
|
||||
vm_statistics64_data_t vmStats;
|
||||
mach_msg_type_number_t count = HOST_VM_INFO64_COUNT;
|
||||
kern_return_t kernReturn = host_statistics64(mach_host_self(),
|
||||
HOST_VM_INFO64,
|
||||
reinterpret_cast<host_info_t>(&vmStats),
|
||||
&count);
|
||||
|
||||
if (kernReturn != KERN_SUCCESS)
|
||||
return false;
|
||||
|
||||
int pageSize;
|
||||
mib[0] = CTL_HW;
|
||||
mib[1] = HW_PAGESIZE;
|
||||
length = sizeof(int);
|
||||
if (sysctl(mib, 2, &pageSize, &length, nullptr, 0) != 0)
|
||||
return false;
|
||||
|
||||
uint64 usedMemory = static_cast<uint64>(vmStats.active_count +
|
||||
vmStats.wire_count +
|
||||
vmStats.compressor_page_count) * pageSize;
|
||||
uint64 availableMemory = static_cast<uint64>(vmStats.free_count +
|
||||
vmStats.inactive_count +
|
||||
vmStats.speculative_count) * pageSize;
|
||||
|
||||
usage.usedPhysicalBytes = usedMemory;
|
||||
usage.availablePhysicalBytes = availableMemory;
|
||||
|
||||
struct xsw_usage swapUsage;
|
||||
mib[0] = CTL_VM;
|
||||
mib[1] = VM_SWAPUSAGE;
|
||||
length = sizeof(swapUsage);
|
||||
if (sysctl(mib, 2, &swapUsage, &length, nullptr, 0) == 0)
|
||||
{
|
||||
usage.totalSwapBytes = swapUsage.xsu_total;
|
||||
usage.usedSwapBytes = swapUsage.xsu_used;
|
||||
}
|
||||
else
|
||||
{
|
||||
usage.totalSwapBytes = 0;
|
||||
usage.usedSwapBytes = 0;
|
||||
}
|
||||
|
||||
usage.totalVirtualBytes = usage.totalPhysicalBytes + usage.totalSwapBytes;
|
||||
usage.usedVirtualBytes = usage.usedPhysicalBytes + usage.usedSwapBytes;
|
||||
|
||||
if (usage.totalPhysicalBytes > 0)
|
||||
{
|
||||
usage.physicalUsagePercent = (static_cast<double>(usage.usedPhysicalBytes) /
|
||||
static_cast<double>(usage.totalPhysicalBytes)) * 100.0;
|
||||
}
|
||||
|
||||
if (usage.totalVirtualBytes > 0)
|
||||
{
|
||||
usage.virtualUsagePercent = (static_cast<double>(usage.usedVirtualBytes) /
|
||||
static_cast<double>(usage.totalVirtualBytes)) * 100.0;
|
||||
}
|
||||
|
||||
usage.hasValidData = true;
|
||||
return true;
|
||||
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string Skyfire::FormatMemorySize(uint64 bytes)
|
||||
{
|
||||
char const* units[] = { "B", "KB", "MB", "GB", "TB" };
|
||||
|
|
@ -142,3 +313,71 @@ std::string Skyfire::FormatProcessMemoryUsage(ProcessMemoryUsage const& usage)
|
|||
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
std::string Skyfire::FormatSystemMemoryUsage(SystemMemoryUsage const& usage)
|
||||
{
|
||||
if (!usage.hasValidData)
|
||||
return "System memory info unavailable";
|
||||
|
||||
std::vector<std::string> fields;
|
||||
|
||||
AppendMemoryField(fields, "Total RAM", usage.totalPhysicalBytes);
|
||||
AppendMemoryField(fields, "Used RAM", usage.usedPhysicalBytes);
|
||||
AppendMemoryField(fields, "Available RAM", usage.availablePhysicalBytes);
|
||||
AppendPercentageField(fields, "RAM Usage", usage.physicalUsagePercent);
|
||||
|
||||
if (usage.totalSwapBytes > 0)
|
||||
{
|
||||
AppendMemoryField(fields, "Total Swap", usage.totalSwapBytes);
|
||||
AppendMemoryField(fields, "Used Swap", usage.usedSwapBytes);
|
||||
}
|
||||
|
||||
if (usage.totalVirtualBytes > 0)
|
||||
{
|
||||
AppendMemoryField(fields, "Total Virtual", usage.totalVirtualBytes);
|
||||
AppendMemoryField(fields, "Used Virtual", usage.usedVirtualBytes);
|
||||
AppendPercentageField(fields, "Virtual Usage", usage.virtualUsagePercent);
|
||||
}
|
||||
|
||||
std::ostringstream stream;
|
||||
for (size_t i = 0; i < fields.size(); ++i)
|
||||
{
|
||||
if (i != 0)
|
||||
stream << ", ";
|
||||
|
||||
stream << fields[i];
|
||||
}
|
||||
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
std::string Skyfire::FormatMemoryUsageSummary(ProcessMemoryUsage const& processUsage,
|
||||
SystemMemoryUsage const& systemUsage)
|
||||
{
|
||||
std::ostringstream stream;
|
||||
|
||||
stream << "Process: " << FormatProcessMemoryUsage(processUsage);
|
||||
|
||||
if (systemUsage.hasValidData)
|
||||
{
|
||||
stream << " | System: ";
|
||||
stream << "RAM " << std::fixed << std::setprecision(1)
|
||||
<< systemUsage.physicalUsagePercent << "% ";
|
||||
stream << "(" << FormatMemorySize(systemUsage.usedPhysicalBytes) << "/"
|
||||
<< FormatMemorySize(systemUsage.totalPhysicalBytes) << ")";
|
||||
|
||||
if (systemUsage.totalSwapBytes > 0)
|
||||
{
|
||||
stream << ", Swap " << std::fixed << std::setprecision(1)
|
||||
<< ((systemUsage.totalSwapBytes > 0) ?
|
||||
(static_cast<double>(systemUsage.usedSwapBytes) /
|
||||
static_cast<double>(systemUsage.totalSwapBytes) * 100.0) : 0.0) << "%";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
stream << " | System info unavailable";
|
||||
}
|
||||
|
||||
return stream.str();
|
||||
}
|
||||
|
|
@ -25,9 +25,28 @@ namespace Skyfire
|
|||
bool hasPrivateBytes = false;
|
||||
};
|
||||
|
||||
struct SystemMemoryUsage
|
||||
{
|
||||
uint64 totalPhysicalBytes = 0;
|
||||
uint64 availablePhysicalBytes = 0;
|
||||
uint64 usedPhysicalBytes = 0;
|
||||
uint64 totalVirtualBytes = 0;
|
||||
uint64 usedVirtualBytes = 0;
|
||||
uint64 totalSwapBytes = 0;
|
||||
uint64 usedSwapBytes = 0;
|
||||
double physicalUsagePercent = 0.0;
|
||||
double virtualUsagePercent = 0.0;
|
||||
|
||||
bool hasValidData = false;
|
||||
};
|
||||
|
||||
bool GetProcessMemoryUsage(ProcessMemoryUsage& usage);
|
||||
bool GetSystemMemoryUsage(SystemMemoryUsage& usage);
|
||||
|
||||
std::string FormatMemorySize(uint64 bytes);
|
||||
std::string FormatProcessMemoryUsage(ProcessMemoryUsage const& usage);
|
||||
std::string FormatSystemMemoryUsage(SystemMemoryUsage const& usage);
|
||||
std::string FormatMemoryUsageSummary(ProcessMemoryUsage const& processUsage, SystemMemoryUsage const& systemUsage);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue