mirror of
https://github.com/cemu-project/Cemu.git
synced 2024-11-27 13:20:29 +00:00
Linux/macOS: Implement overlay CPU/memory statistics (#480)
This commit is contained in:
parent
c17097369b
commit
9ce52ad83a
@ -12,30 +12,16 @@
|
|||||||
#include "imgui/imgui_extension.h"
|
#include "imgui/imgui_extension.h"
|
||||||
|
|
||||||
#include "input/InputManager.h"
|
#include "input/InputManager.h"
|
||||||
|
#include "util/SystemInfo/SystemInfo.h"
|
||||||
|
|
||||||
#include <cinttypes>
|
#include <cinttypes>
|
||||||
|
|
||||||
#if BOOST_OS_WINDOWS
|
|
||||||
#include <Psapi.h>
|
|
||||||
#include <winternl.h>
|
|
||||||
#pragma comment(lib, "ntdll.lib")
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct OverlayStats
|
struct OverlayStats
|
||||||
{
|
{
|
||||||
OverlayStats() {};
|
OverlayStats() {};
|
||||||
|
|
||||||
int processor_count = 1;
|
int processor_count = 1;
|
||||||
|
ProcessorTime processor_time_cemu;
|
||||||
// cemu cpu stats
|
|
||||||
uint64_t last_cpu{}, kernel{}, user{};
|
|
||||||
|
|
||||||
// global cpu stats
|
|
||||||
struct ProcessorTime
|
|
||||||
{
|
|
||||||
uint64_t idle{}, kernel{}, user{};
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<ProcessorTime> processor_times;
|
std::vector<ProcessorTime> processor_times;
|
||||||
|
|
||||||
double fps{};
|
double fps{};
|
||||||
@ -562,19 +548,38 @@ void LatteOverlay_render(bool pad_view)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void LatteOverlay_init()
|
void LatteOverlay_init()
|
||||||
{
|
{
|
||||||
#if BOOST_OS_WINDOWS
|
g_state.processor_count = GetProcessorCount();
|
||||||
SYSTEM_INFO sys_info;
|
|
||||||
GetSystemInfo(&sys_info);
|
|
||||||
g_state.processor_count = sys_info.dwNumberOfProcessors;
|
|
||||||
|
|
||||||
g_state.processor_times.resize(g_state.processor_count);
|
g_state.processor_times.resize(g_state.processor_count);
|
||||||
g_state.cpu_per_core.resize(g_state.processor_count);
|
g_state.cpu_per_core.resize(g_state.processor_count);
|
||||||
#else
|
}
|
||||||
g_state.processor_count = 1;
|
|
||||||
#endif
|
static void UpdateStats_CemuCpu()
|
||||||
|
{
|
||||||
|
ProcessorTime now;
|
||||||
|
QueryProcTime(now);
|
||||||
|
|
||||||
|
double cpu = ProcessorTime::Compare(g_state.processor_time_cemu, now);
|
||||||
|
cpu /= g_state.processor_count;
|
||||||
|
|
||||||
|
g_state.cpu_usage = cpu * 100;
|
||||||
|
g_state.processor_time_cemu = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void UpdateStats_CpuPerCore()
|
||||||
|
{
|
||||||
|
std::vector<ProcessorTime> now(g_state.processor_count);
|
||||||
|
QueryCoreTimes(g_state.processor_count, now);
|
||||||
|
|
||||||
|
for (int32_t i = 0; i < g_state.processor_count; ++i)
|
||||||
|
{
|
||||||
|
double cpu = ProcessorTime::Compare(g_state.processor_times[i], now[i]);
|
||||||
|
|
||||||
|
g_state.cpu_per_core[i] = cpu * 100;
|
||||||
|
g_state.processor_times[i] = now[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LatteOverlay_updateStats(double fps, sint32 drawcalls)
|
void LatteOverlay_updateStats(double fps, sint32 drawcalls)
|
||||||
@ -584,61 +589,11 @@ void LatteOverlay_updateStats(double fps, sint32 drawcalls)
|
|||||||
|
|
||||||
g_state.fps = fps;
|
g_state.fps = fps;
|
||||||
g_state.draw_calls_per_frame = drawcalls;
|
g_state.draw_calls_per_frame = drawcalls;
|
||||||
|
UpdateStats_CemuCpu();
|
||||||
#if BOOST_OS_WINDOWS
|
UpdateStats_CpuPerCore();
|
||||||
// update cemu cpu
|
|
||||||
FILETIME ftime, fkernel, fuser;
|
|
||||||
LARGE_INTEGER now, kernel, user;
|
|
||||||
GetSystemTimeAsFileTime(&ftime);
|
|
||||||
now.LowPart = ftime.dwLowDateTime;
|
|
||||||
now.HighPart = ftime.dwHighDateTime;
|
|
||||||
|
|
||||||
GetProcessTimes(GetCurrentProcess(), &ftime, &ftime, &fkernel, &fuser);
|
|
||||||
kernel.LowPart = fkernel.dwLowDateTime;
|
|
||||||
kernel.HighPart = fkernel.dwHighDateTime;
|
|
||||||
|
|
||||||
user.LowPart = fuser.dwLowDateTime;
|
|
||||||
user.HighPart = fuser.dwHighDateTime;
|
|
||||||
|
|
||||||
double percent = (kernel.QuadPart - g_state.kernel) + (user.QuadPart - g_state.user);
|
|
||||||
percent /= (now.QuadPart - g_state.last_cpu);
|
|
||||||
percent /= g_state.processor_count;
|
|
||||||
g_state.cpu_usage = percent * 100;
|
|
||||||
g_state.last_cpu = now.QuadPart;
|
|
||||||
g_state.user = user.QuadPart;
|
|
||||||
g_state.kernel = kernel.QuadPart;
|
|
||||||
|
|
||||||
// update cpu per core
|
|
||||||
std::vector<SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION> sppi(g_state.processor_count);
|
|
||||||
if (NT_SUCCESS(NtQuerySystemInformation(SystemProcessorPerformanceInformation, sppi.data(), sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * g_state.processor_count, nullptr)))
|
|
||||||
{
|
|
||||||
for (sint32 i = 0; i < g_state.processor_count; ++i)
|
|
||||||
{
|
|
||||||
const uint64 kernel_diff = sppi[i].KernelTime.QuadPart - g_state.processor_times[i].kernel;
|
|
||||||
const uint64 user_diff = sppi[i].UserTime.QuadPart - g_state.processor_times[i].user;
|
|
||||||
const uint64 idle_diff = sppi[i].IdleTime.QuadPart - g_state.processor_times[i].idle;
|
|
||||||
|
|
||||||
const auto total = kernel_diff + user_diff; // kernel time already includes idletime
|
|
||||||
const double cpu = total == 0 ? 0 : (1.0 - ((double)idle_diff / total)) * 100.0;
|
|
||||||
|
|
||||||
g_state.cpu_per_core[i] = cpu;
|
|
||||||
//total_cpu += cpu;
|
|
||||||
|
|
||||||
g_state.processor_times[i].idle = sppi[i].IdleTime.QuadPart;
|
|
||||||
g_state.processor_times[i].kernel = sppi[i].KernelTime.QuadPart;
|
|
||||||
g_state.processor_times[i].user = sppi[i].UserTime.QuadPart;
|
|
||||||
}
|
|
||||||
|
|
||||||
//total_cpu /= g_state.processor_count;
|
|
||||||
//g_state.cpu_usage = total_cpu;
|
|
||||||
}
|
|
||||||
|
|
||||||
// update ram
|
// update ram
|
||||||
PROCESS_MEMORY_COUNTERS pmc{};
|
g_state.ram_usage = (QueryRamUsage() / 1000) / 1000;
|
||||||
pmc.cb = sizeof(pmc);
|
|
||||||
GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc));
|
|
||||||
g_state.ram_usage = (pmc.WorkingSetSize / 1000) / 1000;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// update vram
|
// update vram
|
||||||
g_renderer->GetVRAMInfo(g_state.vramUsage, g_state.vramTotal);
|
g_renderer->GetVRAMInfo(g_state.vramUsage, g_state.vramTotal);
|
||||||
|
@ -98,7 +98,10 @@ void LattePerformanceMonitor_frameEnd()
|
|||||||
performanceMonitor.cycle[nextCycleIndex].recompilerLeaveCount = 0;
|
performanceMonitor.cycle[nextCycleIndex].recompilerLeaveCount = 0;
|
||||||
performanceMonitor.cycle[nextCycleIndex].threadLeaveCount = 0;
|
performanceMonitor.cycle[nextCycleIndex].threadLeaveCount = 0;
|
||||||
performanceMonitor.cycleIndex = nextCycleIndex;
|
performanceMonitor.cycleIndex = nextCycleIndex;
|
||||||
|
|
||||||
|
// next update in 1 second
|
||||||
|
performanceMonitor.cycle[performanceMonitor.cycleIndex].lastUpdate = GetTickCount();
|
||||||
|
|
||||||
if (isFirstUpdate)
|
if (isFirstUpdate)
|
||||||
{
|
{
|
||||||
LatteOverlay_updateStats(0.0, 0);
|
LatteOverlay_updateStats(0.0, 0);
|
||||||
@ -109,8 +112,6 @@ void LattePerformanceMonitor_frameEnd()
|
|||||||
LatteOverlay_updateStats(fps, drawCallCounter / elapsedFrames);
|
LatteOverlay_updateStats(fps, drawCallCounter / elapsedFrames);
|
||||||
gui_updateWindowTitles(false, false, fps);
|
gui_updateWindowTitles(false, false, fps);
|
||||||
}
|
}
|
||||||
// next update in 1 second
|
|
||||||
performanceMonitor.cycle[performanceMonitor.cycleIndex].lastUpdate = GetTickCount();
|
|
||||||
|
|
||||||
// prevent hibernation and screen saver/monitor off
|
// prevent hibernation and screen saver/monitor off
|
||||||
#if BOOST_OS_WINDOWS
|
#if BOOST_OS_WINDOWS
|
||||||
@ -124,4 +125,4 @@ void LattePerformanceMonitor_frameBegin()
|
|||||||
{
|
{
|
||||||
performanceMonitor.vk.numDrawBarriersPerFrame.reset();
|
performanceMonitor.vk.numDrawBarriersPerFrame.reset();
|
||||||
performanceMonitor.vk.numBeginRenderpassPerFrame.reset();
|
performanceMonitor.vk.numBeginRenderpassPerFrame.reset();
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,6 @@ add_library(CemuUtil
|
|||||||
DXGIWrapper/DXGIWrapper.h
|
DXGIWrapper/DXGIWrapper.h
|
||||||
EventService.h
|
EventService.h
|
||||||
Fiber/Fiber.h
|
Fiber/Fiber.h
|
||||||
Fiber/FiberUnix.cpp
|
|
||||||
Fiber/FiberWin.cpp
|
|
||||||
helpers/ClassWrapper.h
|
helpers/ClassWrapper.h
|
||||||
helpers/ConcurrentQueue.h
|
helpers/ConcurrentQueue.h
|
||||||
helpers/enum_array.hpp
|
helpers/enum_array.hpp
|
||||||
@ -50,8 +48,8 @@ add_library(CemuUtil
|
|||||||
math/vector2.h
|
math/vector2.h
|
||||||
math/vector3.h
|
math/vector3.h
|
||||||
MemMapper/MemMapper.h
|
MemMapper/MemMapper.h
|
||||||
MemMapper/MemMapperUnix.cpp
|
SystemInfo/SystemInfo.cpp
|
||||||
MemMapper/MemMapperWin.cpp
|
SystemInfo/SystemInfo.h
|
||||||
ThreadPool/ThreadPool.cpp
|
ThreadPool/ThreadPool.cpp
|
||||||
ThreadPool/ThreadPool.h
|
ThreadPool/ThreadPool.h
|
||||||
tinyxml2/tinyxml2.cpp
|
tinyxml2/tinyxml2.cpp
|
||||||
@ -71,6 +69,23 @@ add_library(CemuUtil
|
|||||||
Zir/Passes/ZpIRRegisterAllocator.cpp
|
Zir/Passes/ZpIRRegisterAllocator.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
target_sources(CemuUtil PRIVATE Fiber/FiberWin.cpp)
|
||||||
|
target_sources(CemuUtil PRIVATE MemMapper/MemMapperWin.cpp)
|
||||||
|
target_sources(CemuUtil PRIVATE SystemInfo/SystemInfoWin.cpp)
|
||||||
|
elseif(UNIX)
|
||||||
|
target_sources(CemuUtil PRIVATE Fiber/FiberUnix.cpp)
|
||||||
|
target_sources(CemuUtil PRIVATE MemMapper/MemMapperUnix.cpp)
|
||||||
|
target_sources(CemuUtil PRIVATE SystemInfo/SystemInfoUnix.cpp)
|
||||||
|
if(NOT APPLE)
|
||||||
|
target_sources(CemuUtil PRIVATE SystemInfo/SystemInfoLinux.cpp)
|
||||||
|
else()
|
||||||
|
target_sources(CemuUtil PRIVATE SystemInfo/SystemInfoMac.cpp)
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
target_sources(CemuUtil PRIVATE SystemInfo/SystemInfoStub.cpp)
|
||||||
|
endif()
|
||||||
|
|
||||||
set_property(TARGET CemuUtil PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
set_property(TARGET CemuUtil PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||||
|
|
||||||
target_include_directories(CemuUtil PUBLIC "../")
|
target_include_directories(CemuUtil PUBLIC "../")
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#include "Fiber.h"
|
#include "Fiber.h"
|
||||||
#if BOOST_OS_LINUX || BOOST_OS_MACOS
|
|
||||||
#include <ucontext.h>
|
#include <ucontext.h>
|
||||||
|
|
||||||
thread_local Fiber* sCurrentFiber{};
|
thread_local Fiber* sCurrentFiber{};
|
||||||
@ -52,5 +51,3 @@ void* Fiber::GetFiberPrivateData()
|
|||||||
{
|
{
|
||||||
return sCurrentFiber->m_privateData;
|
return sCurrentFiber->m_privateData;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
@ -1,5 +1,4 @@
|
|||||||
#include "Fiber.h"
|
#include "Fiber.h"
|
||||||
#if BOOST_OS_WINDOWS
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
|
||||||
thread_local Fiber* sCurrentFiber{};
|
thread_local Fiber* sCurrentFiber{};
|
||||||
@ -39,5 +38,3 @@ void* Fiber::GetFiberPrivateData()
|
|||||||
{
|
{
|
||||||
return sCurrentFiber->m_privateData;
|
return sCurrentFiber->m_privateData;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
@ -1,6 +1,5 @@
|
|||||||
#include "util/MemMapper/MemMapper.h"
|
#include "util/MemMapper/MemMapper.h"
|
||||||
|
|
||||||
#if BOOST_OS_LINUX || BOOST_OS_MACOS
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
|
||||||
@ -65,5 +64,3 @@ namespace MemMapper
|
|||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
|
@ -1,7 +1,5 @@
|
|||||||
#include "util/MemMapper/MemMapper.h"
|
#include "util/MemMapper/MemMapper.h"
|
||||||
|
|
||||||
#if BOOST_OS_WINDOWS
|
|
||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
|
||||||
namespace MemMapper
|
namespace MemMapper
|
||||||
@ -63,5 +61,3 @@ namespace MemMapper
|
|||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
|
34
src/util/SystemInfo/SystemInfo.cpp
Normal file
34
src/util/SystemInfo/SystemInfo.cpp
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#include "util/SystemInfo/SystemInfo.h"
|
||||||
|
|
||||||
|
uint64 ProcessorTime::work()
|
||||||
|
{
|
||||||
|
return user + kernel;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 ProcessorTime::total()
|
||||||
|
{
|
||||||
|
return idle + user + kernel;
|
||||||
|
}
|
||||||
|
|
||||||
|
double ProcessorTime::Compare(ProcessorTime &last, ProcessorTime &now)
|
||||||
|
{
|
||||||
|
auto dwork = now.work() - last.work();
|
||||||
|
auto dtotal = now.total() - last.total();
|
||||||
|
|
||||||
|
return (double)dwork / dtotal;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 GetProcessorCount()
|
||||||
|
{
|
||||||
|
return std::thread::hardware_concurrency();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QueryProcTime(ProcessorTime &out)
|
||||||
|
{
|
||||||
|
uint64 now, user, kernel;
|
||||||
|
QueryProcTime(now, user, kernel);
|
||||||
|
|
||||||
|
out.idle = now - (user + kernel);
|
||||||
|
out.kernel = kernel;
|
||||||
|
out.user = user;
|
||||||
|
}
|
17
src/util/SystemInfo/SystemInfo.h
Normal file
17
src/util/SystemInfo/SystemInfo.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
struct ProcessorTime
|
||||||
|
{
|
||||||
|
uint64 idle{}, kernel{}, user{};
|
||||||
|
|
||||||
|
uint64 work();
|
||||||
|
uint64 total();
|
||||||
|
|
||||||
|
static double Compare(ProcessorTime &last, ProcessorTime &now);
|
||||||
|
};
|
||||||
|
|
||||||
|
uint32 GetProcessorCount();
|
||||||
|
uint64 QueryRamUsage();
|
||||||
|
void QueryProcTime(uint64 &out_now, uint64 &out_user, uint64 &out_kernel);
|
||||||
|
void QueryProcTime(ProcessorTime &out);
|
||||||
|
void QueryCoreTimes(uint32 count, std::vector<ProcessorTime>& out);
|
48
src/util/SystemInfo/SystemInfoLinux.cpp
Normal file
48
src/util/SystemInfo/SystemInfoLinux.cpp
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#include "util/SystemInfo/SystemInfo.h"
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
uint64 QueryRamUsage()
|
||||||
|
{
|
||||||
|
static long page_size = sysconf(_SC_PAGESIZE);
|
||||||
|
if (page_size == -1)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ifstream file("/proc/self/statm");
|
||||||
|
if (file)
|
||||||
|
{
|
||||||
|
file.ignore(std::numeric_limits<std::streamsize>::max(), ' ');
|
||||||
|
uint64 pages;
|
||||||
|
file >> pages;
|
||||||
|
|
||||||
|
return pages * page_size;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QueryCoreTimes(uint32 count, std::vector<ProcessorTime>& out)
|
||||||
|
{
|
||||||
|
std::ifstream file("/proc/stat");
|
||||||
|
if (file)
|
||||||
|
{
|
||||||
|
file.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
|
||||||
|
|
||||||
|
for (auto i = 0; i < out.size(); ++i)
|
||||||
|
{
|
||||||
|
uint64 user, nice, kernel, idle;
|
||||||
|
file.ignore(std::numeric_limits<std::streamsize>::max(), ' ');
|
||||||
|
file >> user >> nice >> kernel >> idle;
|
||||||
|
file.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
|
||||||
|
|
||||||
|
out[i].idle = idle;
|
||||||
|
out[i].kernel = kernel;
|
||||||
|
out[i].user = user + nice;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (auto i = 0; i < count; ++i) out[i] = { };
|
||||||
|
}
|
||||||
|
}
|
62
src/util/SystemInfo/SystemInfoMac.cpp
Normal file
62
src/util/SystemInfo/SystemInfoMac.cpp
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
#include "util/SystemInfo/SystemInfo.h"
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <mach/mach.h>
|
||||||
|
|
||||||
|
#include <mach/processor_info.h>
|
||||||
|
#include <mach/mach_host.h>
|
||||||
|
#include <mach/kern_return.h>
|
||||||
|
|
||||||
|
// borrowed from https://en.wikichip.org/wiki/resident_set_size#OS_X
|
||||||
|
uint64 QueryRamUsage()
|
||||||
|
{
|
||||||
|
mach_task_basic_info info;
|
||||||
|
mach_msg_type_number_t count = MACH_TASK_BASIC_INFO_COUNT;
|
||||||
|
if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&info, &count) == KERN_SUCCESS)
|
||||||
|
return info.resident_size;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// apple official documentation is non-existsent.
|
||||||
|
// based on https://github.com/giampaolo/psutil/blob/master/psutil/_psutil_osx.c#L623
|
||||||
|
void QueryCoreTimes(uint32 count, std::vector<ProcessorTime>& out)
|
||||||
|
{
|
||||||
|
// initialize default
|
||||||
|
for (auto i = 0; i < out.size(); ++i)
|
||||||
|
{
|
||||||
|
out[i] = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
natural_t cpu_count;
|
||||||
|
processor_info_array_t info_array;
|
||||||
|
mach_msg_type_number_t info_count;
|
||||||
|
kern_return_t error;
|
||||||
|
|
||||||
|
mach_port_t host_port = mach_host_self();
|
||||||
|
error = host_processor_info(host_port, PROCESSOR_CPU_LOAD_INFO, &cpu_count, &info_array, &info_count);
|
||||||
|
mach_port_deallocate(mach_task_self(), host_port);
|
||||||
|
|
||||||
|
if (error != KERN_SUCCESS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
processor_cpu_load_info_data_t* cpuLoad = (processor_cpu_load_info_data_t*) info_array;
|
||||||
|
|
||||||
|
for (auto i = 0; i < cpu_count; ++i)
|
||||||
|
{
|
||||||
|
uint64 system = cpuLoad[i].cpu_ticks[CPU_STATE_SYSTEM];
|
||||||
|
uint64 user = cpuLoad[i].cpu_ticks[CPU_STATE_USER] + cpuLoad[i].cpu_ticks[CPU_STATE_NICE];
|
||||||
|
uint64 idle = cpuLoad[i].cpu_ticks[CPU_STATE_IDLE];
|
||||||
|
|
||||||
|
out[i].idle = idle;
|
||||||
|
out[i].kernel = system;
|
||||||
|
out[i].user = user;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = vm_deallocate(mach_task_self(), (vm_address_t) info_array,
|
||||||
|
info_count * sizeof(int));
|
||||||
|
if (ret != KERN_SUCCESS)
|
||||||
|
cemuLog_force("vm_deallocate() failed");
|
||||||
|
}
|
21
src/util/SystemInfo/SystemInfoStub.cpp
Normal file
21
src/util/SystemInfo/SystemInfoStub.cpp
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#include "util/SystemInfo/SystemInfo.h"
|
||||||
|
|
||||||
|
uint64 QueryRamUsage()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QueryProcTime(uint64 &out_now, uint64 &out_user, uint64 &out_kernel)
|
||||||
|
{
|
||||||
|
out_now = 0;
|
||||||
|
out_user = 0;
|
||||||
|
out_kernel = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QueryCoreTimes(uint32 count, std::vector<ProcessorTime>& out)
|
||||||
|
{
|
||||||
|
for (auto i = 0; i < out.size(); ++i)
|
||||||
|
{
|
||||||
|
out[i] = { };
|
||||||
|
}
|
||||||
|
}
|
15
src/util/SystemInfo/SystemInfoUnix.cpp
Normal file
15
src/util/SystemInfo/SystemInfoUnix.cpp
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#include "util/SystemInfo/SystemInfo.h"
|
||||||
|
|
||||||
|
#include <sys/times.h>
|
||||||
|
|
||||||
|
void QueryProcTime(uint64 &out_now, uint64 &out_user, uint64 &out_kernel)
|
||||||
|
{
|
||||||
|
struct tms time_info;
|
||||||
|
clock_t clock_now = times(&time_info);
|
||||||
|
clock_t clock_user = time_info.tms_utime;
|
||||||
|
clock_t clock_kernel = time_info.tms_stime;
|
||||||
|
out_now = static_cast<uint64>(clock_now);
|
||||||
|
out_user = static_cast<uint64>(clock_user);
|
||||||
|
out_kernel = static_cast<uint64>(clock_kernel);
|
||||||
|
}
|
||||||
|
|
69
src/util/SystemInfo/SystemInfoWin.cpp
Normal file
69
src/util/SystemInfo/SystemInfoWin.cpp
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#include "util/SystemInfo/SystemInfo.h"
|
||||||
|
|
||||||
|
#include <Psapi.h>
|
||||||
|
#include <winternl.h>
|
||||||
|
#pragma comment(lib, "ntdll.lib")
|
||||||
|
|
||||||
|
uint64 QueryRamUsage()
|
||||||
|
{
|
||||||
|
PROCESS_MEMORY_COUNTERS pmc{};
|
||||||
|
pmc.cb = sizeof(pmc);
|
||||||
|
if (GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc)))
|
||||||
|
{
|
||||||
|
return pmc.WorkingSetSize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QueryProcTime(uint64 &out_now, uint64 &out_user, uint64 &out_kernel)
|
||||||
|
{
|
||||||
|
FILETIME ftime, fkernel, fuser;
|
||||||
|
LARGE_INTEGER now, kernel, user;
|
||||||
|
GetSystemTimeAsFileTime(&ftime);
|
||||||
|
now.LowPart = ftime.dwLowDateTime;
|
||||||
|
now.HighPart = ftime.dwHighDateTime;
|
||||||
|
|
||||||
|
if (GetProcessTimes(GetCurrentProcess(), &ftime, &ftime, &fkernel, &fuser))
|
||||||
|
{
|
||||||
|
kernel.LowPart = fkernel.dwLowDateTime;
|
||||||
|
kernel.HighPart = fkernel.dwHighDateTime;
|
||||||
|
|
||||||
|
user.LowPart = fuser.dwLowDateTime;
|
||||||
|
user.HighPart = fuser.dwHighDateTime;
|
||||||
|
|
||||||
|
out_now = now.QuadPart;
|
||||||
|
out_user = user.QuadPart;
|
||||||
|
out_kernel = kernel.QuadPart;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out_now = 0;
|
||||||
|
out_user = 0;
|
||||||
|
out_kernel = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QueryCoreTimes(uint32 count, std::vector<ProcessorTime>& out)
|
||||||
|
{
|
||||||
|
std::vector<SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION> sppi(count);
|
||||||
|
if (NT_SUCCESS(NtQuerySystemInformation(SystemProcessorPerformanceInformation, sppi.data(), sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * count, nullptr)))
|
||||||
|
{
|
||||||
|
for (auto i = 0; i < out.size(); ++i)
|
||||||
|
{
|
||||||
|
out[i].idle = sppi[i].IdleTime.QuadPart;
|
||||||
|
out[i].kernel = sppi[i].KernelTime.QuadPart;
|
||||||
|
out[i].kernel -= out[i].idle;
|
||||||
|
out[i].user = sppi[i].UserTime.QuadPart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (auto i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
out[i] = { };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user