diff options
author | Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com) <spamtrap@nedprod.com> | 2021-09-08 17:58:28 +0300 |
---|---|---|
committer | Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com) <spamtrap@nedprod.com> | 2021-09-08 17:58:28 +0300 |
commit | afbac282eda46b9d6cc6b8ab9a959fcdbe1ef606 (patch) | |
tree | d076bad1000c286dc65ad727c9cda7bbebf46ab9 /include | |
parent | bcc600db9feb6aa50e0880422a071d0e39ae74aa (diff) |
current_process_memory_usage: Add system memory stats.
Diffstat (limited to 'include')
-rw-r--r-- | include/llfio/revision.hpp | 6 | ||||
-rw-r--r-- | include/llfio/v2.0/detail/impl/posix/utils.ipp | 340 | ||||
-rw-r--r-- | include/llfio/v2.0/detail/impl/windows/import.hpp | 28 | ||||
-rw-r--r-- | include/llfio/v2.0/detail/impl/windows/utils.ipp | 61 | ||||
-rw-r--r-- | include/llfio/v2.0/utils.hpp | 24 |
5 files changed, 287 insertions, 172 deletions
diff --git a/include/llfio/revision.hpp b/include/llfio/revision.hpp index 08851c80..d7f4cf22 100644 --- a/include/llfio/revision.hpp +++ b/include/llfio/revision.hpp @@ -1,4 +1,4 @@ // Note the second line of this file must ALWAYS be the git SHA, third line ALWAYS the git SHA update time -#define LLFIO_PREVIOUS_COMMIT_REF 8cec4ff8fcd601b774c0ed882fe869e73d23d136 -#define LLFIO_PREVIOUS_COMMIT_DATE "2021-08-30 14:53:35 +00:00" -#define LLFIO_PREVIOUS_COMMIT_UNIQUE 8cec4ff8 +#define LLFIO_PREVIOUS_COMMIT_REF bcc600db9feb6aa50e0880422a071d0e39ae74aa +#define LLFIO_PREVIOUS_COMMIT_DATE "2021-08-30 15:08:05 +00:00" +#define LLFIO_PREVIOUS_COMMIT_UNIQUE bcc600db diff --git a/include/llfio/v2.0/detail/impl/posix/utils.ipp b/include/llfio/v2.0/detail/impl/posix/utils.ipp index 15fe1a5a..ccd634e1 100644 --- a/include/llfio/v2.0/detail/impl/posix/utils.ipp +++ b/include/llfio/v2.0/detail/impl/posix/utils.ipp @@ -341,156 +341,187 @@ namespace utils private_paged_in = ??? MISSING */ - if(!(want & process_memory_usage::want::private_committed) || (want & process_memory_usage::want::private_committed_inaccurate)) + process_memory_usage ret; + if(!!(want & process_memory_usage::want::this_process)) { - process_memory_usage ret; - if((want & process_memory_usage::want::total_address_space_in_use) || (want & process_memory_usage::want::total_address_space_paged_in) || - (want & process_memory_usage::want::private_paged_in)) - { - std::vector<char> buffer(256); - OUTCOME_TRY(fill_buffer(buffer, "/proc/self/statm")); - if(buffer.size() > 1) - { - size_t file_and_shared_pages_paged_in = 0; - sscanf(buffer.data(), "%zu %zu %zu", &ret.total_address_space_in_use, &ret.total_address_space_paged_in, &file_and_shared_pages_paged_in); - ret.private_paged_in = ret.total_address_space_paged_in - file_and_shared_pages_paged_in; - ret.total_address_space_in_use *= page_size(); - ret.total_address_space_paged_in *= page_size(); - ret.private_paged_in *= page_size(); - //std::cout << string_view(buffer.data(), buffer.size()) << std::endl; - } - } - if(want & process_memory_usage::want::private_committed) + if(!(want & process_memory_usage::want::private_committed) || (want & process_memory_usage::want::private_committed_inaccurate)) { - std::vector<char> smaps_rollup(256), maps(65536); - auto r = fill_buffer(smaps_rollup, "/proc/self/smaps_rollup"); - if(!r) + if((want & process_memory_usage::want::total_address_space_in_use) || (want & process_memory_usage::want::total_address_space_paged_in) || + (want & process_memory_usage::want::private_paged_in)) { - if(r.error() == errc::no_such_file_or_directory) + std::vector<char> buffer(256); + OUTCOME_TRY(fill_buffer(buffer, "/proc/self/statm")); + if(buffer.size() > 1) { - // Linux kernel is too old - return errc::operation_not_supported; + size_t file_and_shared_pages_paged_in = 0; + sscanf(buffer.data(), "%zu %zu %zu", &ret.total_address_space_in_use, &ret.total_address_space_paged_in, &file_and_shared_pages_paged_in); + ret.private_paged_in = ret.total_address_space_paged_in - file_and_shared_pages_paged_in; + ret.total_address_space_in_use *= page_size(); + ret.total_address_space_paged_in *= page_size(); + ret.private_paged_in *= page_size(); + // std::cout << string_view(buffer.data(), buffer.size()) << std::endl; } - return std::move(r).error(); } - OUTCOME_TRY(fill_buffer(maps, "/proc/self/maps")); - uint64_t lazyfree = 0; + if(want & process_memory_usage::want::private_committed) { - string_view i(smaps_rollup.data(), smaps_rollup.size()); - OUTCOME_TRY(lazyfree, parse(i, "\nLazyFree:")); + std::vector<char> smaps_rollup(256), maps(65536); + auto r = fill_buffer(smaps_rollup, "/proc/self/smaps_rollup"); + if(!r) + { + if(r.error() == errc::no_such_file_or_directory) + { + // Linux kernel is too old + return errc::operation_not_supported; + } + return std::move(r).error(); + } + OUTCOME_TRY(fill_buffer(maps, "/proc/self/maps")); + uint64_t lazyfree = 0; + { + string_view i(smaps_rollup.data(), smaps_rollup.size()); + OUTCOME_TRY(lazyfree, parse(i, "\nLazyFree:")); + } + string_view i(maps.data(), maps.size()); + size_t anonymous = 0; + for(size_t idx = 0;;) + { + idx = i.find("\n", idx); + if(idx == i.npos) + { + break; + } + idx++; + size_t start = 0, end = 0, inode = 1; + char read = 0, write = 0, executable = 0, private_ = 0; + sscanf(i.data() + idx, "%zx-%zx %c%c%c%c %*u %*u:%*u %zd", &start, &end, &read, &write, &executable, &private_, &inode); + if(inode == 0 && read == 'r' && write == 'w' && executable == '-' && private_ == 'p') + { + anonymous += end - start; + // std::cout << (end - start) << " " << i.substr(idx, 40) << std::endl; + } + } + if(lazyfree != (uint64_t) -1) + { + anonymous -= (size_t) lazyfree; + } + ret.private_committed = anonymous; } - string_view i(maps.data(), maps.size()); - size_t anonymous = 0; - for(size_t idx = 0;;) + } + else + { + std::vector<char> buffer(1024 * 1024); + OUTCOME_TRY(fill_buffer(buffer, "/proc/self/smaps")); + const string_view totalview(buffer.data(), buffer.size()); + // std::cerr << totalview << std::endl; + std::vector<string_view> anon_entries, non_anon_entries; + anon_entries.reserve(32); + non_anon_entries.reserve(32); + auto find_item = [&](size_t idx) -> string_view { + auto x = totalview.rfind("\nSize:", idx); + if(x == string_view::npos) + { + return {}; + } + x = totalview.rfind("\n", x - 1); + if(x == string_view::npos) + { + x = 0; + } + else + { + x++; + } + return totalview.substr(x, idx - x); + }; + for(string_view item = find_item(totalview.size()); item != string_view(); item = find_item(item.data() - totalview.data())) { - idx = i.find("\n", idx); - if(idx == i.npos) + // std::cout << "***" << item << "***"; + // hexaddr-hexaddr flags offset dev:id inode [path] + size_t inode = 1; + sscanf(item.data(), "%*x-%*x %*c%*c%*c%*c %*x %*c%*c:%*c%*c %zu", &inode); + auto vmflagsidx = item.rfind("\nVmFlags:"); + if(vmflagsidx == string_view::npos) { - break; + return errc::illegal_byte_sequence; + } + // Is there " ac" after vmflagsidx? + if(string_view::npos != item.find(" ac", vmflagsidx) && inode == 0) + { + // std::cerr << "Adding anon entry at offset " << itemtopidx << std::endl; + anon_entries.push_back(item); } - idx++; - size_t start = 0, end = 0, inode = 1; - char read = 0, write = 0, executable = 0, private_ = 0; - sscanf(i.data() + idx, "%zx-%zx %c%c%c%c %*u %*u:%*u %zd", &start, &end, &read, &write, &executable, &private_, &inode); - if(inode == 0 && read == 'r' && write == 'w' && executable == '-' && private_ == 'p') + else { - anonymous += end - start; - // std::cout << (end - start) << " " << i.substr(idx, 40) << std::endl; + // std::cerr << "Adding non-anon entry at offset " << itemtopidx << std::endl; + non_anon_entries.push_back(item); } } - if(lazyfree != (uint64_t) -1) + // std::cerr << "Anon entries:"; + for(auto &i : anon_entries) { - anonymous -= (size_t) lazyfree; + OUTCOME_TRY(auto &&size, parse(i, "\nSize:")); + OUTCOME_TRY(auto &&rss, parse(i, "\nRss:")); + OUTCOME_TRY(auto &&anonymous, parse(i, "\nAnonymous:")); + OUTCOME_TRY(auto &&lazyfree, parse(i, "\nLazyFree:")); + if(size != (uint64_t) -1 && rss != (uint64_t) -1 && anonymous != (uint64_t) -1) + { + ret.total_address_space_in_use += size; + ret.total_address_space_paged_in += rss; + ret.private_committed += anonymous; + if(lazyfree != (uint64_t) -1) + { + ret.total_address_space_paged_in -= lazyfree; + ret.private_committed -= lazyfree; + } + ret.private_paged_in += rss; + } + // std::cerr << i << "\nSize = " << size << " Rss = " << rss << std::endl; } - ret.private_committed = anonymous; - } - return ret; - } - std::vector<char> buffer(1024 * 1024); - OUTCOME_TRY(fill_buffer(buffer, "/proc/self/smaps")); - const string_view totalview(buffer.data(), buffer.size()); - // std::cerr << totalview << std::endl; - std::vector<string_view> anon_entries, non_anon_entries; - anon_entries.reserve(32); - non_anon_entries.reserve(32); - auto find_item = [&](size_t idx) -> string_view { - auto x = totalview.rfind("\nSize:", idx); - if(x == string_view::npos) - { - return {}; - } - x = totalview.rfind("\n", x - 1); - if(x == string_view::npos) - { - x = 0; - } - else - { - x++; - } - return totalview.substr(x, idx - x); - }; - for(string_view item = find_item(totalview.size()); item != string_view(); item = find_item(item.data() - totalview.data())) - { - // std::cout << "***" << item << "***"; - // hexaddr-hexaddr flags offset dev:id inode [path] - size_t inode = 1; - sscanf(item.data(), "%*x-%*x %*c%*c%*c%*c %*x %*c%*c:%*c%*c %zu", &inode); - auto vmflagsidx = item.rfind("\nVmFlags:"); - if(vmflagsidx == string_view::npos) - { - return errc::illegal_byte_sequence; - } - // Is there " ac" after vmflagsidx? - if(string_view::npos != item.find(" ac", vmflagsidx) && inode == 0) - { - // std::cerr << "Adding anon entry at offset " << itemtopidx << std::endl; - anon_entries.push_back(item); - } - else - { - // std::cerr << "Adding non-anon entry at offset " << itemtopidx << std::endl; - non_anon_entries.push_back(item); - } - } - process_memory_usage ret; - // std::cerr << "Anon entries:"; - for(auto &i : anon_entries) - { - OUTCOME_TRY(auto &&size, parse(i, "\nSize:")); - OUTCOME_TRY(auto &&rss, parse(i, "\nRss:")); - OUTCOME_TRY(auto &&anonymous, parse(i, "\nAnonymous:")); - OUTCOME_TRY(auto &&lazyfree, parse(i, "\nLazyFree:")); - if(size != (uint64_t) -1 && rss != (uint64_t) -1 && anonymous != (uint64_t) -1) - { - ret.total_address_space_in_use += size; - ret.total_address_space_paged_in += rss; - ret.private_committed += anonymous; - if(lazyfree != (uint64_t) -1) + // std::cerr << "\n\nNon-anon entries:"; + for(auto &i : non_anon_entries) { - ret.total_address_space_paged_in -= lazyfree; - ret.private_committed -= lazyfree; + OUTCOME_TRY(auto &&size, parse(i, "\nSize:")); + OUTCOME_TRY(auto &&rss, parse(i, "\nRss:")); + OUTCOME_TRY(auto &&lazyfree, parse(i, "\nLazyFree:")); + if(size != (uint64_t) -1 && rss != (uint64_t) -1) + { + ret.total_address_space_in_use += size; + ret.total_address_space_paged_in += rss; + if(lazyfree != (uint64_t) -1) + { + ret.total_address_space_in_use -= lazyfree; + } + } + // std::cerr << i << "\nSize = " << size << " Rss = " << rss << std::endl; } - ret.private_paged_in += rss; } - // std::cerr << i << "\nSize = " << size << " Rss = " << rss << std::endl; } - // std::cerr << "\n\nNon-anon entries:"; - for(auto &i : non_anon_entries) + if(!!(want & process_memory_usage::want::this_system)) { - OUTCOME_TRY(auto &&size, parse(i, "\nSize:")); - OUTCOME_TRY(auto &&rss, parse(i, "\nRss:")); - OUTCOME_TRY(auto &&lazyfree, parse(i, "\nLazyFree:")); - if(size != (uint64_t) -1 && rss != (uint64_t) -1) + std::vector<char> buffer(1024); + OUTCOME_TRY(fill_buffer(buffer, "/proc/meminfo")); + if(buffer.size() > 1) { - ret.total_address_space_in_use += size; - ret.total_address_space_paged_in += rss; - if(lazyfree != (uint64_t) -1) + string_view i(buffer.data(), buffer.size()); + OUTCOME_TRY(ret.system_physical_memory_total, parse(i, "MemTotal:")); + OUTCOME_TRY(ret.system_physical_memory_available, parse(i, "\nMemAvailable:")); + if((uint64_t) -1 == ret.system_physical_memory_available) { - ret.total_address_space_in_use -= lazyfree; + // MemAvailable is >= Linux 3.14, so let's approximate what it would be + OUTCOME_TRY(auto &&memfree, parse(i, "\nMemFree:")); + OUTCOME_TRY(auto &&cached, parse(i, "\nCached:")); + OUTCOME_TRY(auto &&swapcached, parse(i, "\nSwapCached:")); + ret.system_physical_memory_available = memfree + cached + swapcached; } + OUTCOME_TRY(ret.system_commit_charge_maximum, parse(i, "\nCommitLimit:")); + OUTCOME_TRY(ret.system_commit_charge_available, parse(i, "\nCommitted_AS:")); + OUTCOME_TRY(auto &&lazyfree, parse(i, "\nLazyFree:")); + if(lazyfree == (uint64_t) -1) + { + lazyfree = 0; + } + ret.system_commit_charge_available = ret.system_commit_charge_maximum - ret.system_commit_charge_available + lazyfree; } - // std::cerr << i << "\nSize = " << size << " Rss = " << rss << std::endl; } return ret; } @@ -502,29 +533,48 @@ namespace utils (void) want; kern_return_t error; mach_msg_type_number_t outCount; - task_vm_info_data_t vmInfo; - // task_kernelmemory_info_data_t kmInfo; + process_memory_usage ret; + if(!!(wanted & process_memory_usage::want::this_process)) + { + task_vm_info_data_t vmInfo; + // task_kernelmemory_info_data_t kmInfo; - outCount = TASK_VM_INFO_COUNT; - error = task_info(mach_task_self(), TASK_VM_INFO, (task_info_t) &vmInfo, &outCount); - if(error != KERN_SUCCESS) + outCount = TASK_VM_INFO_COUNT; + error = task_info(mach_task_self(), TASK_VM_INFO, (task_info_t) &vmInfo, &outCount); + if(error != KERN_SUCCESS) + { + return errc::invalid_argument; + } + // outCount = TASK_KERNELMEMORY_INFO_COUNT; + // error = task_info(mach_task_self(), TASK_KERNELMEMORY_INFO, (task_info_t)&kmInfo, &outCount); + // if (error != KERN_SUCCESS) { + // return errc::invalid_argument; + //} + // std::cout << vmInfo.virtual_size << "\n" << vmInfo.region_count << "\n" << vmInfo.resident_size << "\n" << vmInfo.device << "\n" << vmInfo.internal << + // "\n" << vmInfo.external << "\n" << vmInfo.reusable << "\n" << vmInfo.purgeable_volatile_pmap<< "\n" << vmInfo.purgeable_volatile_resident << "\n" << + // vmInfo.purgeable_volatile_virtual << "\n" << vmInfo.compressed << "\n" << vmInfo.phys_footprint << std::endl; std::cout << "\n" << kmInfo.total_palloc + // << + // "\n" << kmInfo.total_pfree << "\n" << kmInfo.total_salloc << "\n" << kmInfo.total_sfree << std::endl; + ret.total_address_space_in_use = vmInfo.virtual_size; + ret.total_address_space_paged_in = vmInfo.resident_size; + ret.private_committed = vmInfo.internal + vmInfo.compressed; + ret.private_paged_in = vmInfo.phys_footprint; + } + if(!!(wanted & process_memory_usage::want::this_system)) { - return errc::invalid_argument; + vm_statistics_data_t vmStat; + outCount = HOST_VM_INFO_COUNT; + error = host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t) &vmStat, &outCount); + if(error != KERN_SUCCESS) + { + return errc::invalid_argument; + } + ret.system_physical_memory_total = ((uint64_t) vmStat.free_count + vmStat.active_count + vmStat.inactive_count + vmStat.wire_count) * page_size(); + ret.system_physical_memory_available = ((uint64_t) vmStat.free_count + vmStat.inactive_count) * page_size(); + // Not sure how to retrieve these on Mac OS + // ret.system_commit_charge_maximum = (uint64_t) pi.CommitLimit * page_size(); + // ret.system_commit_charge_available = (uint64_t) pi.CommitTotal * page_size(); } - // outCount = TASK_KERNELMEMORY_INFO_COUNT; - // error = task_info(mach_task_self(), TASK_KERNELMEMORY_INFO, (task_info_t)&kmInfo, &outCount); - // if (error != KERN_SUCCESS) { - // return errc::invalid_argument; - //} - // std::cout << vmInfo.virtual_size << "\n" << vmInfo.region_count << "\n" << vmInfo.resident_size << "\n" << vmInfo.device << "\n" << vmInfo.internal << - // "\n" << vmInfo.external << "\n" << vmInfo.reusable << "\n" << vmInfo.purgeable_volatile_pmap<< "\n" << vmInfo.purgeable_volatile_resident << "\n" << - // vmInfo.purgeable_volatile_virtual << "\n" << vmInfo.compressed << "\n" << vmInfo.phys_footprint << std::endl; std::cout << "\n" << kmInfo.total_palloc << - // "\n" << kmInfo.total_pfree << "\n" << kmInfo.total_salloc << "\n" << kmInfo.total_sfree << std::endl; - process_memory_usage ret; - ret.total_address_space_in_use = vmInfo.virtual_size; - ret.total_address_space_paged_in = vmInfo.resident_size; - ret.private_committed = vmInfo.internal + vmInfo.compressed; - ret.private_paged_in = vmInfo.phys_footprint; return ret; #else #error Unknown platform diff --git a/include/llfio/v2.0/detail/impl/windows/import.hpp b/include/llfio/v2.0/detail/impl/windows/import.hpp index 71001ce6..dd4b0ac2 100644 --- a/include/llfio/v2.0/detail/impl/windows/import.hpp +++ b/include/llfio/v2.0/detail/impl/windows/import.hpp @@ -539,6 +539,26 @@ namespace windows_nt_kernel using DiscardVirtualMemory_t = BOOL(NTAPI *)(_In_ PVOID VirtualAddress, _In_ SIZE_T Size); + typedef struct _PERFORMANCE_INFORMATION + { + DWORD cb; + SIZE_T CommitTotal; + SIZE_T CommitLimit; + SIZE_T CommitPeak; + SIZE_T PhysicalTotal; + SIZE_T PhysicalAvailable; + SIZE_T SystemCache; + SIZE_T KernelTotal; + SIZE_T KernelPaged; + SIZE_T KernelNonpaged; + SIZE_T PageSize; + DWORD HandleCount; + DWORD ProcessCount; + DWORD ThreadCount; + } PERFORMANCE_INFORMATION, *PPERFORMANCE_INFORMATION, PERFORMACE_INFORMATION, *PPERFORMACE_INFORMATION; + + using GetPerformanceInfo_t = BOOL(NTAPI*)(PPERFORMANCE_INFORMATION pPerformanceInformation, DWORD cb); + using RtlCaptureStackBackTrace_t = USHORT(NTAPI *)(_In_ ULONG FramesToSkip, _In_ ULONG FramesToCapture, _Out_ PVOID *BackTrace, _Out_opt_ PULONG BackTraceHash); @@ -965,6 +985,7 @@ namespace windows_nt_kernel static AdjustTokenPrivileges_t AdjustTokenPrivileges; static PrefetchVirtualMemory_t PrefetchVirtualMemory_; static DiscardVirtualMemory_t DiscardVirtualMemory_; + static GetPerformanceInfo_t GetPerformanceInfo; static SymInitialize_t SymInitialize; static SymGetLineFromAddr64_t SymGetLineFromAddr64; static RtlCaptureStackBackTrace_t RtlCaptureStackBackTrace; @@ -1300,6 +1321,13 @@ namespace windows_nt_kernel { DiscardVirtualMemory_ = reinterpret_cast<DiscardVirtualMemory_t>(GetProcAddress(kernel32, "DiscardVirtualMemory")); } + if(GetPerformanceInfo == nullptr) + { + if((GetPerformanceInfo = reinterpret_cast<GetPerformanceInfo_t>(GetProcAddress(kernel32, "K32GetPerformanceInfo"))) == nullptr) + { + abort(); + } + } #ifdef LLFIO_OP_STACKBACKTRACEDEPTH if(dbghelp) { diff --git a/include/llfio/v2.0/detail/impl/windows/utils.ipp b/include/llfio/v2.0/detail/impl/windows/utils.ipp index e12db462..4557e567 100644 --- a/include/llfio/v2.0/detail/impl/windows/utils.ipp +++ b/include/llfio/v2.0/detail/impl/windows/utils.ipp @@ -207,38 +207,55 @@ namespace utils return success(); } - result<process_memory_usage> current_process_memory_usage(process_memory_usage::want /*unused*/) noexcept + result<process_memory_usage> current_process_memory_usage(process_memory_usage::want wanted) noexcept { // Amazingly Win32 doesn't expose private working set, so to avoid having // to iterate all the pages in the process and calculate, use a hidden // NT kernel call windows_nt_kernel::init(); using namespace windows_nt_kernel; - ULONG written = 0; - _VM_COUNTERS_EX2 vmc; - memset(&vmc, 0, sizeof(vmc)); - NTSTATUS ntstat = NtQueryInformationProcess(GetCurrentProcess(), ProcessVmCounters, &vmc, sizeof(vmc), &written); - if(ntstat < 0) - { - return ntkernel_error(ntstat); - } process_memory_usage ret; - /* Notes: + if(!!(wanted & process_memory_usage::want::this_process)) + { + ULONG written = 0; + _VM_COUNTERS_EX2 vmc; + memset(&vmc, 0, sizeof(vmc)); + NTSTATUS ntstat = NtQueryInformationProcess(GetCurrentProcess(), ProcessVmCounters, &vmc, sizeof(vmc), &written); + if(ntstat < 0) + { + return ntkernel_error(ntstat); + } + /* Notes: - Apparently PrivateUsage is the commit charge on Windows. It always equals PagefileUsage. - It is the total amount of private anonymous pages committed. - SharedCommitUsage is amount of non-binary Shared memory committed. - Therefore total non-binary commit = PrivateUsage + SharedCommitUsage + Apparently PrivateUsage is the commit charge on Windows. It always equals PagefileUsage. + It is the total amount of private anonymous pages committed. + SharedCommitUsage is amount of non-binary Shared memory committed. + Therefore total non-binary commit = PrivateUsage + SharedCommitUsage - WorkingSetSize is the total amount of program binaries, non-binary shared memory, and anonymous pages faulted in. - PrivateWorkingSetSize is the amount of private anonymous pages faulted into the process. - Therefore remainder is all shared working set faulted into the process. - */ - ret.total_address_space_in_use = vmc.VirtualSize; - ret.total_address_space_paged_in = vmc.WorkingSetSize; + WorkingSetSize is the total amount of program binaries, non-binary shared memory, and anonymous pages faulted in. + PrivateWorkingSetSize is the amount of private anonymous pages faulted into the process. + Therefore remainder is all shared working set faulted into the process. + */ + ret.total_address_space_in_use = vmc.VirtualSize; + ret.total_address_space_paged_in = vmc.WorkingSetSize; - ret.private_committed = vmc.PrivateUsage; - ret.private_paged_in = vmc.PrivateWorkingSetSize; + ret.private_committed = vmc.PrivateUsage; + ret.private_paged_in = vmc.PrivateWorkingSetSize; + } + if(!!(wanted & process_memory_usage::want::this_system)) + { + PERFORMANCE_INFORMATION pi; + memset(&pi, 0, sizeof(pi)); + pi.cb = sizeof(pi); + if(!GetPerformanceInfo(&pi, sizeof(pi))) + { + return win32_error(); + } + ret.system_physical_memory_total = (uint64_t) pi.PhysicalTotal * pi.PageSize; + ret.system_physical_memory_available = (uint64_t) pi.PhysicalAvailable * pi.PageSize; + ret.system_commit_charge_maximum = (uint64_t) pi.CommitLimit * pi.PageSize; + ret.system_commit_charge_available = (uint64_t)(pi.CommitLimit - pi.CommitTotal) * pi.PageSize; + } return ret; } diff --git a/include/llfio/v2.0/utils.hpp b/include/llfio/v2.0/utils.hpp index 147dfc7b..4b8501da 100644 --- a/include/llfio/v2.0/utils.hpp +++ b/include/llfio/v2.0/utils.hpp @@ -205,11 +205,31 @@ namespace utils total_address_space_paged_in = 1U << 1U, private_committed = 1U << 2U, private_paged_in = 1U << 3U, + private_committed_inaccurate = 1U << 8U, - all = (unsigned) -1 // + system_physical_memory_total = 1U << 16U, + system_physical_memory_available = 1U << 17U, + system_commit_charge_maximum = 1U << 18U, + system_commit_charge_available = 1U << 19U, + + this_process = 0x0000ffff, // + this_system = 0xffff0000, // + all = 0xffffffff // } QUICKCPPLIB_BITFIELD_END(want) + //! The total physical memory in this system. + uint64_t system_physical_memory_total{0}; + //! The physical memory in this system not containing dirty pages i.e. is currently used for file system caching, or unused. + uint64_t system_physical_memory_available{0}; + + //! The maximum amount of memory which can be committed by all processes. This is typically physical RAM plus swap files. Note that swap files can be added + //! and removed over time. + uint64_t system_commit_charge_maximum{0}; + //! The amount of commit charge remaining before the maximum. Subtract this from `system_commit_charge_maximum` to determine the amount of commit charge + //! consumed by all processes in the system. + uint64_t system_commit_charge_available{0}; + //! The total virtual address space in use. size_t total_address_space_in_use{0}; //! The total memory currently paged into the process. Always `<= total_address_space_in_use`. Also known as "working set", or "resident set size including @@ -248,7 +268,7 @@ namespace utils We therefore supply as `private_committed` the same value as `private_paged_in`. */ LLFIO_HEADERS_ONLY_FUNC_SPEC result<process_memory_usage> - current_process_memory_usage(process_memory_usage::want want = process_memory_usage::want::all) noexcept; + current_process_memory_usage(process_memory_usage::want want = process_memory_usage::want::this_process) noexcept; /*! \brief CPU usage statistics for a process. */ |