From 5544436fd6654fcc6cd6b3a9c3f3b9b7e0b21865 Mon Sep 17 00:00:00 2001 From: "Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)" Date: Tue, 3 Aug 2021 18:23:27 +0100 Subject: Add utils::current_process_cpu_usage(). --- include/llfio/revision.hpp | 6 +- include/llfio/v2.0/detail/impl/posix/utils.ipp | 197 +++++++++++++++++++---- include/llfio/v2.0/detail/impl/windows/utils.ipp | 36 ++++- include/llfio/v2.0/utils.hpp | 51 ++++++ test/tests/utils.cpp | 76 ++++++--- 5 files changed, 313 insertions(+), 53 deletions(-) diff --git a/include/llfio/revision.hpp b/include/llfio/revision.hpp index 424376d1..905c3a59 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 a93b8521afb5d858f423de7accdc6d9d4504e7cb -#define LLFIO_PREVIOUS_COMMIT_DATE "2021-05-11 18:16:38 +00:00" -#define LLFIO_PREVIOUS_COMMIT_UNIQUE a93b8521 +#define LLFIO_PREVIOUS_COMMIT_REF d867bd612097979ca40b07852abbf7332538ab98 +#define LLFIO_PREVIOUS_COMMIT_DATE "2021-08-03 17:03:03 +00:00" +#define LLFIO_PREVIOUS_COMMIT_UNIQUE d867bd61 diff --git a/include/llfio/v2.0/detail/impl/posix/utils.ipp b/include/llfio/v2.0/detail/impl/posix/utils.ipp index e3b47484..1461ae8f 100644 --- a/include/llfio/v2.0/detail/impl/posix/utils.ipp +++ b/include/llfio/v2.0/detail/impl/posix/utils.ipp @@ -32,6 +32,9 @@ Distributed under the Boost Software License, Version 1.0. #include // for preadv #endif #ifdef __APPLE__ +#include +#include +#include #include #include #endif @@ -259,7 +262,7 @@ namespace utils buffer.resize(buffer.size() * 2); } const string_view totalview(buffer.data(), buffer.size()); - //std::cerr << totalview << std::endl; + // std::cerr << totalview << std::endl; std::vector anon_entries, non_anon_entries; anon_entries.reserve(32); non_anon_entries.reserve(32); @@ -298,16 +301,17 @@ namespace utils // 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; + // 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; + // std::cerr << "Adding non-anon entry at offset " << itemtopidx << std::endl; non_anon_entries.push_back(item); } } - auto parse = [](string_view item, string_view what) ->result { auto idx = item.find(what); + auto parse = [](string_view item, string_view what) -> result { + auto idx = item.find(what); if(string_view::npos == idx) { return (uint64_t) -1; @@ -359,7 +363,7 @@ namespace utils return value; }; process_memory_usage ret; - //std::cerr << "Anon entries:"; + // std::cerr << "Anon entries:"; for(auto &i : anon_entries) { OUTCOME_TRY(auto &&size, parse(i, "\nSize:")); @@ -378,9 +382,9 @@ namespace utils ret.private_paged_in -= lazyfree; } } - //std::cerr << i << "\nSize = " << size << " Rss = " << rss << std::endl; + // std::cerr << i << "\nSize = " << size << " Rss = " << rss << std::endl; } - //std::cerr << "\n\nNon-anon entries:"; + // std::cerr << "\n\nNon-anon entries:"; for(auto &i : non_anon_entries) { OUTCOME_TRY(auto &&size, parse(i, "\nSize:")); @@ -395,7 +399,7 @@ namespace utils ret.total_address_space_paged_in -= lazyfree; } } - //std::cerr << i << "\nSize = " << size << " Rss = " << rss << std::endl; + // std::cerr << i << "\nSize = " << size << " Rss = " << rss << std::endl; } return ret; } @@ -404,32 +408,167 @@ namespace utils return error_from_exception(); } #elif defined(__APPLE__) - kern_return_t error; - mach_msg_type_number_t outCount; - task_vm_info_data_t vmInfo; - //task_kernelmemory_info_data_t kmInfo; + kern_return_t error; + mach_msg_type_number_t outCount; + 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) { - return errc::invalid_argument; + 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; + 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 +#endif } - //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; + + result current_process_cpu_usage() noexcept + { + process_cpu_usage ret; + memset(&ret, 0, sizeof(ret)); +#ifdef __linux__ + try + { + /* Need to multiply all below by 1000000000ULL / sysconf(_SC_CLK_TCK) + + /proc/[pid]/stat: + + %*d %*s %*c %*d %*d %*d %*d %*d %*u %*lu %*lu %*lu %*lu %lu %lu + + The last two are process user time and process kernel time. + + /proc/stat: + + cpu + */ + std::vector buffer1(65536), buffer2(65536); + auto fill_buffer = [](std::vector &buffer, const char *path) -> result { + for(;;) + { + int ih = ::open(path, O_RDONLY); + if(ih == -1) + { + return posix_error(); + } + size_t totalbytesread = 0; + for(;;) + { + auto bytesread = ::read(ih, buffer.data() + totalbytesread, buffer.size() - totalbytesread); + if(bytesread < 0) + { + ::close(ih); + return posix_error(); + } + if(bytesread == 0) + { + break; + } + totalbytesread += bytesread; + } + ::close(ih); + if(totalbytesread < buffer.size()) + { + buffer.resize(totalbytesread); + break; + } + buffer.resize(buffer.size() * 2); + } + return success(); + }; + static const uint64_t ts_multiplier = 1000000000ULL / sysconf(_SC_CLK_TCK); + OUTCOME_TRY(fill_buffer(buffer1, "/proc/self/stat")); + OUTCOME_TRY(fill_buffer(buffer2, "/proc/stat")); + if(sscanf(buffer1.data(), "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %lu %lu", &ret.process_ns_in_user_mode, + &ret.process_ns_in_kernel_mode) < 2) + { + return errc::protocol_error; + } + uint64_t user_nice; + if(sscanf(buffer2.data(), "cpu %lu %lu %lu %lu", &ret.system_ns_in_user_mode, &user_nice, &ret.system_ns_in_kernel_mode, &ret.system_ns_in_idle_mode) < + 4) + { + return errc::protocol_error; + } + ret.system_ns_in_user_mode += user_nice; + ret.process_ns_in_user_mode *= ts_multiplier; + ret.process_ns_in_kernel_mode *= ts_multiplier; + ret.system_ns_in_user_mode *= ts_multiplier; + ret.system_ns_in_kernel_mode *= ts_multiplier; + ret.system_ns_in_idle_mode *= ts_multiplier; + return ret; + } + catch(...) + { + return error_from_exception(); + } +#elif defined(__APPLE__) + kern_return_t error; + mach_msg_type_number_t outCount; + task_basic_info_64 processInfo1; + task_thread_times_info processInfo2; + + outCount = TASK_BASIC_INFO_64_COUNT; + error = task_info(mach_task_self(), TASK_BASIC_INFO_64, (task_info_t) &processInfo1, &outCount); + if(error != KERN_SUCCESS) + { + return errc::invalid_argument; + } + outCount = TASK_THREAD_TIMES_INFO_COUNT; + error = task_info(mach_task_self(), TASK_THREAD_TIMES_INFO, (task_info_t) &processInfo2, &outCount); + if(error != KERN_SUCCESS) + { + return errc::invalid_argument; + } + ret.process_ns_in_user_mode = (processInfo1.user_time.seconds + processInfo2.user_time.seconds) * 1000000000ULL + + (processInfo1.user_time.microseconds + processInfo2.user_time.microseconds) * 1000ULL; + ret.process_ns_in_kernel_mode = (processInfo1.system_time.seconds + processInfo2.system_time.seconds) * 1000000000ULL + + (processInfo1.system_time.microseconds + processInfo2.system_time.microseconds) * 1000ULL; + + natural_t numCPU = 0; + processor_info_array_t cpuInfo; + mach_msg_type_number_t numCpuInfo; + error = host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &numCPU, &cpuInfo, &numCpuInfo); + if(error != KERN_SUCCESS) + { + return errc::invalid_argument; + } + for(natural_t n = 0; n < numCPU; n++) + { + ret.system_ns_in_user_mode += cpuInfo[CPU_STATE_MAX * n + CPU_STATE_USER] + cpuInfo[CPU_STATE_MAX * n + CPU_STATE_NICE]; + ret.system_ns_in_kernel_mode += cpuInfo[CPU_STATE_MAX * n + CPU_STATE_SYSTEM]; + ret.system_ns_in_idle_mode += cpuInfo[CPU_STATE_MAX * n + CPU_STATE_IDLE]; + } + vm_deallocate(mach_task_self(), cpuInfo, sizeof(integer_t) * numCPUInfo); + static const double ts_multiplier = [] { + mach_timebase_info_data_t timebase; + mach_timebase_info(&timebase); + return (double) timebase.numer / timebase.denom; + }; + ret.system_ns_in_user_mode = (uint64_t)(ts_multiplier * ret.system_ns_in_user_mode); + ret.system_ns_in_kernel_mode = (uint64_t)(ts_multiplier * ret.system_ns_in_kernel_mode); + ret.system_ns_in_idle_mode = (uint64_t)(ts_multiplier * ret.system_ns_in_idle_mode); + return ret; #else #error Unknown platform #endif + return ret; } namespace detail diff --git a/include/llfio/v2.0/detail/impl/windows/utils.ipp b/include/llfio/v2.0/detail/impl/windows/utils.ipp index 0735b4d2..d4516000 100644 --- a/include/llfio/v2.0/detail/impl/windows/utils.ipp +++ b/include/llfio/v2.0/detail/impl/windows/utils.ipp @@ -129,7 +129,8 @@ namespace utils tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - if(AdjustTokenPrivileges(processToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), static_cast(nullptr), static_cast(nullptr)) == 0) + if(AdjustTokenPrivileges(processToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), static_cast(nullptr), static_cast(nullptr)) == + 0) { return win32_error(); } @@ -184,7 +185,8 @@ namespace utils tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - if(AdjustTokenPrivileges(processToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), static_cast(nullptr), static_cast(nullptr)) == 0) + if(AdjustTokenPrivileges(processToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), static_cast(nullptr), static_cast(nullptr)) == + 0) { return win32_error(); } @@ -205,7 +207,8 @@ namespace utils return success(); } - result current_process_memory_usage() noexcept { + result current_process_memory_usage() 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 @@ -239,6 +242,33 @@ namespace utils return ret; } + result current_process_cpu_usage() noexcept + { + process_cpu_usage ret; + memset(&ret, 0, sizeof(ret)); + { + FILETIME IdleTime, KernelTime, UserTime; + if(GetSystemTimes(&IdleTime, &KernelTime, &UserTime) == 0) + { + return win32_error(); + } + ret.system_ns_in_idle_mode = (((uint64_t) IdleTime.dwHighDateTime << 32U) | IdleTime.dwLowDateTime) * 100; + ret.system_ns_in_kernel_mode = (((uint64_t) KernelTime.dwHighDateTime << 32U) | KernelTime.dwLowDateTime) * 100; + ret.system_ns_in_user_mode = (((uint64_t) UserTime.dwHighDateTime << 32U) | UserTime.dwLowDateTime) * 100; + } + { + FILETIME CreationTime, ExitTime, KernelTime, UserTime; + if(GetProcessTimes(GetCurrentProcess(), &CreationTime, &ExitTime, &KernelTime, &UserTime) == 0) + { + return win32_error(); + } + // Is it worth adjusting KernelTime and UserTime by QueryProcessCycleTime to make them TSC granularity? + ret.process_ns_in_kernel_mode = (((uint64_t) KernelTime.dwHighDateTime << 32U) | KernelTime.dwLowDateTime) * 100; + ret.process_ns_in_user_mode = (((uint64_t) UserTime.dwHighDateTime << 32U) | UserTime.dwLowDateTime) * 100; + } + return ret; + } + namespace detail { large_page_allocation allocate_large_pages(size_t bytes) diff --git a/include/llfio/v2.0/utils.hpp b/include/llfio/v2.0/utils.hpp index c50514f7..da524ac7 100644 --- a/include/llfio/v2.0/utils.hpp +++ b/include/llfio/v2.0/utils.hpp @@ -208,12 +208,63 @@ namespace utils //! The total anonymous memory currently paged into the process. Always `<= private_committed`. Also known as "active anonymous pages". size_t private_paged_in{0}; }; + static_assert(std::is_trivially_copyable::value, "process_memory_usage is not trivially copyable!"); + /*! \brief Retrieve the current memory usage statistics for this process. \note Mac OS provides no way of reading how much memory a process has committed. We therefore supply as `private_committed` the same value as `private_paged_in`. */ LLFIO_HEADERS_ONLY_FUNC_SPEC result current_process_memory_usage() noexcept; + /*! \brief CPU usage statistics for a process. + */ + struct process_cpu_usage + { + //! The amount of nanoseconds all processes ever have spent in user mode. + uint64_t system_ns_in_user_mode; + //! The amount of nanoseconds all processes ever have spent in kernel mode. + uint64_t system_ns_in_kernel_mode; + //! The amount of nanoseconds all processes ever have spent in idle mode. + uint64_t system_ns_in_idle_mode; + + //! The amount of nanoseconds this process has spent in user mode. + uint64_t process_ns_in_user_mode; + //! The amount of nanoseconds this process has spent in kernel mode. + uint64_t process_ns_in_kernel_mode; + + //! Subtracts an earlier result from a later result. + process_cpu_usage operator-(const process_cpu_usage &o) const noexcept + { + return {system_ns_in_user_mode - o.system_ns_in_user_mode, system_ns_in_kernel_mode - o.system_ns_in_kernel_mode, + system_ns_in_idle_mode - o.system_ns_in_idle_mode, process_ns_in_user_mode - o.process_ns_in_user_mode, + process_ns_in_kernel_mode - o.process_ns_in_kernel_mode}; + } + //! Subtracts an earlier result from a later result. + process_cpu_usage &operator-=(const process_cpu_usage &o) noexcept + { + system_ns_in_user_mode -= o.system_ns_in_user_mode; + system_ns_in_kernel_mode -= o.system_ns_in_kernel_mode; + system_ns_in_idle_mode -= o.system_ns_in_idle_mode; + process_ns_in_user_mode -= o.process_ns_in_user_mode; + process_ns_in_kernel_mode -= o.process_ns_in_kernel_mode; + return *this; + } + }; + static_assert(std::is_trivially_copyable::value, "process_cpu_usage is not trivially copyable!"); + + /*! \brief Retrieve the current CPU usage statistics for this system and this process. These + are unsigned counters which always increment, and so may eventually wrap. + + The simplest way to use this API is to call it whilst also taking the current monotonic + clock/CPU TSC and then calculating the delta change over that period of time. + + \note The returned values may not be a snapshot accurate against one another as they + may get derived from multiple sources. Also, granularity is probably either a lot more + than one nanosecond on most platforms, but may be CPU TSC based on others (you can test + it to be sure). + */ + LLFIO_HEADERS_ONLY_FUNC_SPEC result current_process_cpu_usage() noexcept; + namespace detail { struct large_page_allocation diff --git a/test/tests/utils.cpp b/test/tests/utils.cpp index 0f4ee3c1..2598156c 100644 --- a/test/tests/utils.cpp +++ b/test/tests/utils.cpp @@ -24,6 +24,36 @@ Distributed under the Boost Software License, Version 1.0. #include "../test_kernel_decl.hpp" +static inline void TestCurrentProcessCPUUsage() +{ + namespace llfio = LLFIO_V2_NAMESPACE; + std::vector threads; + std::atomic done{0}; + for(size_t n = 0; n < std::thread::hardware_concurrency() / 4; n++) + { + threads.push_back(std::thread([&] { + while(!done) + { + } + })); + } + llfio::utils::process_cpu_usage pcu1 = llfio::utils::current_process_cpu_usage().value(); + std::this_thread::sleep_for(std::chrono::seconds(1)); + llfio::utils::process_cpu_usage pcu2 = llfio::utils::current_process_cpu_usage().value(); + auto diff = pcu2 - pcu1; + BOOST_CHECK(diff.process_ns_in_user_mode >= 900000000ULL * std::thread::hardware_concurrency() / 4); + BOOST_CHECK(diff.system_ns_in_user_mode >= 900000000ULL * std::thread::hardware_concurrency() / 4); + BOOST_CHECK(diff.system_ns_in_idle_mode <= 1100000000ULL * std::thread::hardware_concurrency() * 3 / 4); + std::cout << "With " << (std::thread::hardware_concurrency() / 4) << " threads busy the process spent " << diff.process_ns_in_user_mode << " ns in user mode and " + << diff.process_ns_in_kernel_mode << " ns in kernel mode. The system spent " << diff.system_ns_in_user_mode << " ns in user mode, " + << diff.system_ns_in_kernel_mode << " ns in kernel mode, and " << diff.system_ns_in_idle_mode << " in idle mode." << std::endl; + done = true; + for(auto &t : threads) + { + t.join(); + } +} + static inline void TestCurrentProcessMemoryUsage() { #if defined(__has_feature) @@ -37,20 +67,21 @@ static inline void TestCurrentProcessMemoryUsage() pmu = llfio::utils::current_process_memory_usage().value(); last_pmu = &pmu; return [](std::ostream &s) -> std::ostream & { - return s << " " << (last_pmu->total_address_space_in_use / 1024.0 / 1024.0) << "," << (last_pmu->total_address_space_paged_in / 1024.0 / 1024.0) << "," << (last_pmu->private_committed / 1024.0 / 1024.0) << "," << (last_pmu->private_paged_in / 1024.0 / 1024.0) << std::endl; + return s << " " << (last_pmu->total_address_space_in_use / 1024.0 / 1024.0) << "," << (last_pmu->total_address_space_paged_in / 1024.0 / 1024.0) + << "," << (last_pmu->private_committed / 1024.0 / 1024.0) << "," << (last_pmu->private_paged_in / 1024.0 / 1024.0) << std::endl; }; }; - auto fakefault = [](llfio::map_handle &maph){ + auto fakefault = [](llfio::map_handle &maph) { #ifdef __APPLE__ - // Mac OS doesn't implement map page table prefaulting at all, - // so fake it so the memory statistics work right - for(size_t n = 0; n < maph.length(); n += 4096) - { - auto *p = (volatile llfio::byte *) maph.address() + n; - *p; - } + // Mac OS doesn't implement map page table prefaulting at all, + // so fake it so the memory statistics work right + for(size_t n = 0; n < maph.length(); n += 4096) + { + auto *p = (volatile llfio::byte *) maph.address() + n; + *p; + } #else - (void) maph; + (void) maph; #endif }; { @@ -103,7 +134,8 @@ static inline void TestCurrentProcessMemoryUsage() maph.do_not_store({maph.address(), maph.length()}).value(); std::cout << " After committing and faulting and do not storing 1Gb:\n" << print(after_do_not_store) << std::endl; } - auto within = [](const llfio::utils::process_memory_usage &a, const llfio::utils::process_memory_usage &b, int total_address_space_in_use, int total_address_space_paged_in, int private_committed, int private_paged_in) { + auto within = [](const llfio::utils::process_memory_usage &a, const llfio::utils::process_memory_usage &b, int total_address_space_in_use, + int total_address_space_paged_in, int private_committed, int private_paged_in) { auto check = [](size_t a, size_t b, int bound) { auto diff = abs((b / 1024.0 / 1024.0) - (a / 1024.0 / 1024.0)); return diff > bound - 10 && diff < bound + 10; @@ -153,34 +185,39 @@ static inline void TestCurrentProcessMemoryUsage() } { // Should raise total_address_space_in_use and total_address_space_paged_in by 1Gb - auto mapfileh = llfio::map_handle::map(sectionh, 1024 * 1024 * 1024, 0, llfio::section_handle::flag::readwrite | llfio::section_handle::flag::prefault).value(); + auto mapfileh = + llfio::map_handle::map(sectionh, 1024 * 1024 * 1024, 0, llfio::section_handle::flag::readwrite | llfio::section_handle::flag::prefault).value(); fakefault(mapfileh); std::cout << " After committing and faulting 1Gb:\n" << print(after_fault) << std::endl; } #ifndef _WIN32 { // Should raise total_address_space_in_use by 1Gb, but not private_committed - auto mapfileh = llfio::map_handle::map(sectionh, 1024 * 1024 * 1024, 0, llfio::section_handle::flag::readwrite | llfio::section_handle::flag::prefault).value(); + auto mapfileh = + llfio::map_handle::map(sectionh, 1024 * 1024 * 1024, 0, llfio::section_handle::flag::readwrite | llfio::section_handle::flag::prefault).value(); fakefault(mapfileh); mapfileh.decommit({mapfileh.address(), mapfileh.length()}).value(); std::cout << " After committing and faulting and decommitting 1Gb:\n" << print(after_decommit) << std::endl; } { // Should raise total_address_space_in_use by 1Gb, but not private_committed - auto mapfileh = llfio::map_handle::map(sectionh, 1024 * 1024 * 1024, 0, llfio::section_handle::flag::readwrite | llfio::section_handle::flag::prefault).value(); + auto mapfileh = + llfio::map_handle::map(sectionh, 1024 * 1024 * 1024, 0, llfio::section_handle::flag::readwrite | llfio::section_handle::flag::prefault).value(); fakefault(mapfileh); mapfileh.zero_memory({mapfileh.address(), mapfileh.length()}).value(); std::cout << " After committing and faulting and zeroing 1Gb:\n" << print(after_zero) << std::endl; } { // Should raise total_address_space_in_use by 1Gb, but not private_committed - auto mapfileh = llfio::map_handle::map(sectionh, 1024 * 1024 * 1024, 0, llfio::section_handle::flag::readwrite | llfio::section_handle::flag::prefault).value(); + auto mapfileh = + llfio::map_handle::map(sectionh, 1024 * 1024 * 1024, 0, llfio::section_handle::flag::readwrite | llfio::section_handle::flag::prefault).value(); fakefault(mapfileh); mapfileh.do_not_store({mapfileh.address(), mapfileh.length()}).value(); std::cout << " After committing and faulting and do not storing 1Gb:\n" << print(after_do_not_store) << std::endl; } #endif - auto within = [](const llfio::utils::process_memory_usage &a, const llfio::utils::process_memory_usage &b, int total_address_space_in_use, int total_address_space_paged_in, int private_committed, int private_paged_in) { + auto within = [](const llfio::utils::process_memory_usage &a, const llfio::utils::process_memory_usage &b, int total_address_space_in_use, + int total_address_space_paged_in, int private_committed, int private_paged_in) { auto check = [](size_t a, size_t b, int bound) { auto diff = abs((b / 1024.0 / 1024.0) - (a / 1024.0 / 1024.0)); return diff > bound - 10 && diff < bound + 10; @@ -196,7 +233,7 @@ static inline void TestCurrentProcessMemoryUsage() BOOST_CHECK(within(before_anything, after_commit, 1024, 0, 0, 0)); BOOST_CHECK(within(before_anything, after_fault, 1024, 1024, 0, 0)); BOOST_CHECK(within(before_anything, after_decommit, 1024, 0, 0, 0)); - BOOST_CHECK(within(before_anything, after_zero, 1024, 1024, 0, 0)); // doesn't implement zero() + BOOST_CHECK(within(before_anything, after_zero, 1024, 1024, 0, 0)); // doesn't implement zero() BOOST_CHECK(within(before_anything, after_do_not_store, 1024, 1024, 0, 0)); // do_not_store() doesn't decrease RSS #else BOOST_CHECK(within(before_anything, after_reserve, 1024, 0, 0, 0)); @@ -215,4 +252,7 @@ static inline void TestCurrentProcessMemoryUsage() } } -KERNELTEST_TEST_KERNEL(integration, llfio, utils, current_process_memory_usage, "Tests that llfio::utils::current_process_memory_usage() works as expected", TestCurrentProcessMemoryUsage()) +KERNELTEST_TEST_KERNEL(integration, llfio, utils, current_process_cpu_usage, "Tests that llfio::utils::current_process_cpu_usage() works as expected", + TestCurrentProcessCPUUsage()) +KERNELTEST_TEST_KERNEL(integration, llfio, utils, current_process_memory_usage, "Tests that llfio::utils::current_process_memory_usage() works as expected", + TestCurrentProcessMemoryUsage()) -- cgit v1.2.3