| #if !defined(spp_memory_h_guard) |
| #define spp_memory_h_guard |
| |
| #include <cstdint> |
| #include <cstring> |
| #include <cstdlib> |
| |
| #if defined(_WIN32) || defined(__CYGWIN__) |
| #define SPP_WIN |
| #endif |
| |
| #ifdef SPP_WIN |
| #include <windows.h> |
| #include <Psapi.h> |
| #undef min |
| #undef max |
| #elif defined(__linux__) |
| #include <sys/types.h> |
| #include <sys/sysinfo.h> |
| #elif defined(__FreeBSD__) |
| #include <paths.h> |
| #include <fcntl.h> |
| #include <kvm.h> |
| #include <unistd.h> |
| #include <sys/sysctl.h> |
| #include <sys/user.h> |
| #endif |
| |
| namespace spp { |
| uint64_t GetSystemMemory(); |
| uint64_t GetTotalMemoryUsed(); |
| uint64_t GetProcessMemoryUsed(); |
| uint64_t GetPhysicalMemory(); |
| |
| uint64_t GetSystemMemory() { |
| #ifdef SPP_WIN |
| MEMORYSTATUSEX memInfo; |
| memInfo.dwLength = sizeof(MEMORYSTATUSEX); |
| GlobalMemoryStatusEx(&memInfo); |
| return static_cast<uint64_t>(memInfo.ullTotalPageFile); |
| #elif defined(__linux__) |
| struct sysinfo memInfo; |
| sysinfo(&memInfo); |
| auto totalVirtualMem = memInfo.totalram; |
| |
| totalVirtualMem += memInfo.totalswap; |
| totalVirtualMem *= memInfo.mem_unit; |
| return static_cast<uint64_t>(totalVirtualMem); |
| #elif defined(__FreeBSD__) |
| kvm_t *kd; |
| u_int pageCnt; |
| size_t pageCntLen = sizeof(pageCnt); |
| u_int pageSize; |
| struct kvm_swap kswap; |
| uint64_t totalVirtualMem; |
| |
| pageSize = static_cast<u_int>(getpagesize()); |
| |
| sysctlbyname("vm.stats.vm.v_page_count", &pageCnt, &pageCntLen, NULL, 0); |
| totalVirtualMem = pageCnt * pageSize; |
| |
| kd = kvm_open(NULL, _PATH_DEVNULL, NULL, O_RDONLY, "kvm_open"); |
| kvm_getswapinfo(kd, &kswap, 1, 0); |
| kvm_close(kd); |
| totalVirtualMem += kswap.ksw_total * pageSize; |
| |
| return totalVirtualMem; |
| #else |
| return 0; |
| #endif |
| } |
| |
| uint64_t GetTotalMemoryUsed() { |
| #ifdef SPP_WIN |
| MEMORYSTATUSEX memInfo; |
| memInfo.dwLength = sizeof(MEMORYSTATUSEX); |
| GlobalMemoryStatusEx(&memInfo); |
| return static_cast<uint64_t>(memInfo.ullTotalPageFile - memInfo.ullAvailPageFile); |
| #elif defined(__linux__) |
| struct sysinfo memInfo; |
| sysinfo(&memInfo); |
| auto virtualMemUsed = memInfo.totalram - memInfo.freeram; |
| |
| virtualMemUsed += memInfo.totalswap - memInfo.freeswap; |
| virtualMemUsed *= memInfo.mem_unit; |
| |
| return static_cast<uint64_t>(virtualMemUsed); |
| #elif defined(__FreeBSD__) |
| kvm_t *kd; |
| u_int pageSize; |
| u_int pageCnt, freeCnt; |
| size_t pageCntLen = sizeof(pageCnt); |
| size_t freeCntLen = sizeof(freeCnt); |
| struct kvm_swap kswap; |
| uint64_t virtualMemUsed; |
| |
| pageSize = static_cast<u_int>(getpagesize()); |
| |
| sysctlbyname("vm.stats.vm.v_page_count", &pageCnt, &pageCntLen, NULL, 0); |
| sysctlbyname("vm.stats.vm.v_free_count", &freeCnt, &freeCntLen, NULL, 0); |
| virtualMemUsed = (pageCnt - freeCnt) * pageSize; |
| |
| kd = kvm_open(NULL, _PATH_DEVNULL, NULL, O_RDONLY, "kvm_open"); |
| kvm_getswapinfo(kd, &kswap, 1, 0); |
| kvm_close(kd); |
| virtualMemUsed += kswap.ksw_used * pageSize; |
| |
| return virtualMemUsed; |
| #else |
| return 0; |
| #endif |
| } |
| |
| uint64_t GetProcessMemoryUsed() { |
| #ifdef SPP_WIN |
| PROCESS_MEMORY_COUNTERS_EX pmc; |
| GetProcessMemoryInfo(GetCurrentProcess(), reinterpret_cast<PPROCESS_MEMORY_COUNTERS>(&pmc), sizeof(pmc)); |
| return static_cast<uint64_t>(pmc.PrivateUsage); |
| #elif defined(__linux__) |
| auto parseLine = [](char* line) -> int { |
| auto i = strlen(line); |
| |
| while (*line < '0' || *line > '9') { |
| line++; |
| } |
| |
| line[i - 3] = '\0'; |
| i = atoi(line); |
| return i; |
| }; |
| |
| auto file = fopen("/proc/self/status", "r"); |
| auto result = -1; |
| char line[128]; |
| |
| while (fgets(line, 128, file) != nullptr) { |
| if (strncmp(line, "VmSize:", 7) == 0) { |
| result = parseLine(line); |
| break; |
| } |
| } |
| |
| fclose(file); |
| return static_cast<uint64_t>(result) * 1024; |
| #elif defined(__FreeBSD__) |
| struct kinfo_proc info; |
| size_t infoLen = sizeof(info); |
| int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid()}; |
| |
| sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &infoLen, NULL, 0); |
| return static_cast<uint64_t>(info.ki_rssize * getpagesize()); |
| #else |
| return 0; |
| #endif |
| } |
| |
| uint64_t GetPhysicalMemory() { |
| #ifdef SPP_WIN |
| MEMORYSTATUSEX memInfo; |
| memInfo.dwLength = sizeof(MEMORYSTATUSEX); |
| GlobalMemoryStatusEx(&memInfo); |
| return static_cast<uint64_t>(memInfo.ullTotalPhys); |
| #elif defined(__linux__) |
| struct sysinfo memInfo; |
| sysinfo(&memInfo); |
| |
| auto totalPhysMem = memInfo.totalram; |
| |
| totalPhysMem *= memInfo.mem_unit; |
| return static_cast<uint64_t>(totalPhysMem); |
| #elif defined(__FreeBSD__) |
| u_long physMem; |
| size_t physMemLen = sizeof(physMem); |
| int mib[] = {CTL_HW, HW_PHYSMEM}; |
| |
| sysctl(mib, sizeof(mib) / sizeof(*mib), &physMem, &physMemLen, NULL, 0); |
| return physMem; |
| #else |
| return 0; |
| #endif |
| } |
| |
| } // namespace spp |
| |
| #endif // spp_memory_h_guard |