From a6318ffdca8576c1f3670fb402e6bb6a697220d6 Mon Sep 17 00:00:00 2001 From: mntone Date: Tue, 27 Jun 2017 14:54:26 +0900 Subject: [PATCH] libobs/util: Add memory usage functions Closes jp9000/obs-studio#953 --- libobs/util/platform-cocoa.m | 65 +++++++++++++++++ libobs/util/platform-nix.c | 124 +++++++++++++++++++++++++++++++++ libobs/util/platform-windows.c | 50 +++++++++++++ libobs/util/platform.h | 12 ++++ 4 files changed, 251 insertions(+) diff --git a/libobs/util/platform-cocoa.m b/libobs/util/platform-cocoa.m index b9f392c9c..f93341cc0 100644 --- a/libobs/util/platform-cocoa.m +++ b/libobs/util/platform-cocoa.m @@ -352,3 +352,68 @@ int os_get_logical_cores(void) os_get_cores_internal(); return logical_cores; } + +static inline bool os_get_sys_memory_usage_internal(vm_statistics_t vmstat) +{ + mach_msg_type_number_t out_count = HOST_VM_INFO_COUNT; + if (host_statistics(mach_host_self(), HOST_VM_INFO, + (host_info_t)vmstat, &out_count) != KERN_SUCCESS) + return false; + return true; +} + +uint64_t os_get_sys_free_size(void) +{ + vm_statistics_data_t vmstat = {}; + if (!os_get_sys_memory_usage_internal(&vmstat)) + return 0; + + return vmstat.free_count * vm_page_size; +} + +#ifndef MACH_TASK_BASIC_INFO +typedef task_basic_info_data_t mach_task_basic_info_data_t; +#endif + +static inline bool os_get_proc_memory_usage_internal( + mach_task_basic_info_data_t *taskinfo) +{ +#ifdef MACH_TASK_BASIC_INFO + const task_flavor_t flavor = MACH_TASK_BASIC_INFO; + mach_msg_type_number_t out_count = MACH_TASK_BASIC_INFO_COUNT; +#else + const task_flavor_t flavor = TASK_BASIC_INFO; + mach_msg_type_number_t out_count = TASK_BASIC_INFO_COUNT; +#endif + if (task_info(mach_task_self(), flavor, + (task_info_t)taskinfo, &out_count) != KERN_SUCCESS) + return false; + return true; +} + +bool os_get_proc_memory_usage(os_proc_memory_usage_t *usage) +{ + mach_task_basic_info_data_t taskinfo = {}; + if (!os_get_proc_memory_usage_internal(&taskinfo)) + return false; + + usage->resident_size = taskinfo.resident_size; + usage->virtual_size = taskinfo.virtual_size; + return true; +} + +uint64_t os_get_proc_resident_size(void) +{ + mach_task_basic_info_data_t taskinfo = {}; + if (!os_get_proc_memory_usage_internal(&taskinfo)) + return 0; + return taskinfo.resident_size; +} + +uint64_t os_get_proc_virtual_size(void) +{ + mach_task_basic_info_data_t taskinfo = {}; + if (!os_get_proc_memory_usage_internal(&taskinfo)) + return 0; + return taskinfo.virtual_size; +} diff --git a/libobs/util/platform-nix.c b/libobs/util/platform-nix.c index 26f606d7b..7b7d3af33 100644 --- a/libobs/util/platform-nix.c +++ b/libobs/util/platform-nix.c @@ -33,6 +33,16 @@ #if !defined(__APPLE__) #include #include +#ifdef __FreeBSD__ +#include +#include +#include +#include +#include +#include +#else +#include +#endif #include #endif @@ -678,6 +688,120 @@ int os_get_logical_cores(void) os_get_cores_internal(); return logical_cores; } + +#ifdef __FreeBSD__ +uint64_t os_get_sys_free_size(void) +{ + uint64_t mem_free = 0; + size_t length = sizeof(mem_free); + if (sysctlbyname("vm.stats.vm.v_free_count", &mem_free, &length, + NULL, 0) < 0) + return 0; + return mem_free; +} + +static inline bool os_get_proc_memory_usage_internal(struct kinfo_proc *kinfo) +{ + int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid()}; + size_t length = sizeof(*kinfo); + if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), kinfo, &length, + NULL, 0) < 0) + return false; + return true; +} + +bool os_get_proc_memory_usage(os_proc_memory_usage_t *usage) +{ + struct kinfo_proc kinfo; + if (!os_get_proc_memory_usage_internal(&kinfo)) + return false; + + usage->resident_size = + (uint64_t)kinfo.ki_rssize * sysconf(_SC_PAGESIZE); + usage->virtual_size = (uint64_t)kinfo.ki_size; + return true; +} + +uint64_t os_get_proc_resident_size(void) +{ + struct kinfo_proc kinfo; + if (!os_get_proc_memory_usage_internal(&kinfo)) + return 0; + return (uint64_t)kinfo.ki_rssize * sysconf(_SC_PAGESIZE); +} + +uint64_t os_get_proc_virtual_size(void) +{ + struct kinfo_proc kinfo; + if (!os_get_proc_memory_usage_internal(&kinfo)) + return 0; + return (uint64_t)kinfo.ki_size; +} +#else +uint64_t os_get_sys_free_size(void) {return 0;} + +typedef struct +{ + unsigned long virtual_size; + unsigned long resident_size; + unsigned long share_pages; + unsigned long text; + unsigned long library; + unsigned long data; + unsigned long dirty_pages; +} statm_t; + +static inline bool os_get_proc_memory_usage_internal(statm_t *statm) +{ + const char *statm_path = "/proc/self/statm"; + + FILE *f = fopen(statm_path, "r"); + if (!f) + return false; + + if (fscanf(f, "%ld %ld %ld %ld %ld %ld %ld", + &statm->virtual_size, + &statm->resident_size, + &statm->share_pages, + &statm->text, + &statm->library, + &statm->data, + &statm->dirty_pages) != 7) { + fclose(f); + return false; + } + + fclose(f); + return true; +} + +bool os_get_proc_memory_usage(os_proc_memory_usage_t *usage) +{ + statm_t statm = {}; + if (!os_get_proc_memory_usage_internal(&statm)) + return false; + + usage->resident_size = statm.resident_size; + usage->virtual_size = statm.virtual_size; + return true; +} + +uint64_t os_get_proc_resident_size(void) +{ + statm_t statm = {}; + if (!os_get_proc_memory_usage_internal(&statm)) + return 0; + return (uint64_t)statm.resident_size; +} + +uint64_t os_get_proc_virtual_size(void) +{ + statm_t statm = {}; + if (!os_get_proc_memory_usage_internal(&statm)) + return 0; + return (uint64_t)statm.virtual_size; +} +#endif #endif uint64_t os_get_free_disk_space(const char *dir) diff --git a/libobs/util/platform-windows.c b/libobs/util/platform-windows.c index 78ab4927b..910a53658 100644 --- a/libobs/util/platform-windows.c +++ b/libobs/util/platform-windows.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "base.h" #include "platform.h" @@ -947,6 +948,55 @@ int os_get_logical_cores(void) return logical_cores; } +static inline bool os_get_sys_memory_usage_internal(MEMORYSTATUSEX *msex) +{ + if (!GlobalMemoryStatusEx(msex)) + return false; + return true; +} + +uint64_t os_get_sys_free_size(void) +{ + MEMORYSTATUSEX msex = {sizeof(MEMORYSTATUSEX)}; + if (!os_get_sys_memory_usage_internal(&msex)) + return 0; + return msex.ullAvailPhys; +} + +static inline bool os_get_proc_memory_usage_internal(PROCESS_MEMORY_COUNTERS *pmc) +{ + if (!GetProcessMemoryInfo(GetCurrentProcess(), pmc, sizeof(*pmc))) + return false; + return true; +} + +bool os_get_proc_memory_usage(os_proc_memory_usage_t *usage) +{ + PROCESS_MEMORY_COUNTERS pmc = {sizeof(PROCESS_MEMORY_COUNTERS)}; + if (!os_get_proc_memory_usage_internal(&pmc)) + return false; + + usage->resident_size = pmc.WorkingSetSize; + usage->virtual_size = pmc.PagefileUsage; + return true; +} + +uint64_t os_get_proc_resident_size(void) +{ + PROCESS_MEMORY_COUNTERS pmc = {sizeof(PROCESS_MEMORY_COUNTERS)}; + if (!os_get_proc_memory_usage_internal(&pmc)) + return 0; + return pmc.WorkingSetSize; +} + +uint64_t os_get_proc_virtual_size(void) +{ + PROCESS_MEMORY_COUNTERS pmc = {sizeof(PROCESS_MEMORY_COUNTERS)}; + if (!os_get_proc_memory_usage_internal(&pmc)) + return 0; + return pmc.PagefileUsage; +} + uint64_t os_get_free_disk_space(const char *dir) { wchar_t *wdir = NULL; diff --git a/libobs/util/platform.h b/libobs/util/platform.h index bf5e2cfd7..cd5eea21f 100644 --- a/libobs/util/platform.h +++ b/libobs/util/platform.h @@ -181,6 +181,18 @@ EXPORT void os_breakpoint(void); EXPORT int os_get_physical_cores(void); EXPORT int os_get_logical_cores(void); +EXPORT uint64_t os_get_sys_free_size(void); + +struct os_proc_memory_usage { + uint64_t resident_size; + uint64_t virtual_size; +}; +typedef struct os_proc_memory_usage os_proc_memory_usage_t; + +EXPORT bool os_get_proc_memory_usage(os_proc_memory_usage_t *usage); +EXPORT uint64_t os_get_proc_resident_size(void); +EXPORT uint64_t os_get_proc_virtual_size(void); + #ifdef _MSC_VER #define strtoll _strtoi64 #if _MSC_VER < 1900 -- GitLab