diff options
Diffstat (limited to 'include/llfio/v2.0/detail/impl/posix/utils.ipp')
-rw-r--r-- | include/llfio/v2.0/detail/impl/posix/utils.ipp | 246 |
1 files changed, 165 insertions, 81 deletions
diff --git a/include/llfio/v2.0/detail/impl/posix/utils.ipp b/include/llfio/v2.0/detail/impl/posix/utils.ipp index 7b734a45..2332ae91 100644 --- a/include/llfio/v2.0/detail/impl/posix/utils.ipp +++ b/include/llfio/v2.0/detail/impl/posix/utils.ipp @@ -214,11 +214,96 @@ namespace utils return false; } - result<process_memory_usage> current_process_memory_usage() noexcept + result<process_memory_usage> current_process_memory_usage(process_memory_usage::want want) noexcept { #ifdef __linux__ try { + auto fill_buffer = [](std::vector<char> &buffer, const char *path) -> result<void> { + 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(); + }; + auto parse = [](string_view item, string_view what) -> result<uint64_t> { + auto idx = item.find(what); + if(string_view::npos == idx) + { + return (uint64_t) -1; + } + idx += what.size(); + for(; item[idx] == ' '; idx++) + ; + auto eidx = idx; + for(; item[eidx] != '\n'; eidx++) + ; + string_view unit(item.substr(eidx - 2, 2)); + uint64_t value = atoll(item.data() + idx); + if(unit == "kB") + { + value *= 1024ULL; + } + else if(unit == "mB") + { + value *= 1024ULL * 1024; + } + else if(unit == "gB") + { + value *= 1024ULL * 1024 * 1024; + } + else if(unit == "tB") + { + value *= 1024ULL * 1024 * 1024 * 1024; + } + else if(unit == "pB") + { + value *= 1024ULL * 1024 * 1024 * 1024 * 1024; + } + else if(unit == "eB") + { + value *= 1024ULL * 1024 * 1024 * 1024 * 1024 * 1024; + } + else if(unit == "zB") + { + value *= 1024ULL * 1024 * 1024 * 1024 * 1024 * 1024 * 1024; + } + else if(unit == "yB") + { + value *= 1024ULL * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024; + } + else + { + return errc::illegal_byte_sequence; + } + return value; + }; /* /proc/[pid]/status: total_address_space_in_use = VmSize @@ -230,40 +315,90 @@ namespace utils total_address_space_in_use = Sum of Size total_address_space_paged_in = Sum of Rss - private_committed = Sum of Size for all entries with VmFlags containing ac, and inode = 0? - private_paged_in = (Sum of Anonymous - Sum of LazyFree) for all entries with VmFlags containing ac, and inode = 0? + private_committed = (Sum of Anonymous - Sum of LazyFree) for all entries with VmFlags containing ac, and inode = 0? + private_paged_in = Sum of Rss for all entries with VmFlags containing ac, and inode = 0? + + /proc/[pid]/maps: + + hexstart-hexend rw-p offset devid:devid inode pathname + + total_address_space_in_use = Sum of regions + total_address_space_paged_in = ??? MISSING + private_committed = Sum of Size for all entries with rw-p, and inode = 0? + private_paged_in = ??? MISSING + + /proc/[pid]/statm: + + %zu %zu %zu ... total_address_space_in_use total_address_space_paged_in file_shared_pages_paged_in + + (values are in pages) + + /proc/[pid]/smaps_rollup: + + total_address_space_in_use = ??? MISSING + total_address_space_paged_in = ??? MISSING + private_committed = Anonymous - LazyFree (but, can't distinguish reservations!) + private_paged_in = ??? MISSING + */ - std::vector<char> buffer(65536); - for(;;) + if(want & process_memory_usage::want::private_committed_inaccurate) { - int ih = ::open("/proc/self/smaps", O_RDONLY); - if(ih == -1) + 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)) { - return posix_error(); + 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; + } } - size_t totalbytesread = 0; - for(;;) + if(want & process_memory_usage::want::private_committed) { - auto bytesread = ::read(ih, buffer.data() + totalbytesread, buffer.size() - totalbytesread); - if(bytesread < 0) + std::vector<char> smaps_rollup(256), maps(65536); + OUTCOME_TRY(fill_buffer(smaps_rollup, "/proc/self/smaps_rollup")); + OUTCOME_TRY(fill_buffer(maps, "/proc/self/maps")); + uint64_t lazyfree = 0; { - ::close(ih); - return posix_error(); + string_view i(smaps_rollup.data(), smaps_rollup.size()); + OUTCOME_TRY(lazyfree, parse(i, "\nLazyFree:")); } - if(bytesread == 0) + string_view i(maps.data(), maps.size()); + size_t anonymous = 0; + for(size_t idx = 0;;) { - break; + 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; + } } - totalbytesread += bytesread; - } - ::close(ih); - if(totalbytesread < buffer.size()) - { - buffer.resize(totalbytesread); - break; + if(lazyfree != (uint64_t) -1) + { + anonymous -= (size_t) lazyfree; + } + ret.private_committed = anonymous; } - buffer.resize(buffer.size() * 2); + 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; @@ -288,7 +423,7 @@ namespace utils }; for(string_view item = find_item(totalview.size()); item != string_view(); item = find_item(item.data() - totalview.data())) { - //std::cout << "***" << item << "***"; + // 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); @@ -309,58 +444,6 @@ namespace utils non_anon_entries.push_back(item); } } - auto parse = [](string_view item, string_view what) -> result<uint64_t> { - auto idx = item.find(what); - if(string_view::npos == idx) - { - return (uint64_t) -1; - } - idx += what.size(); - for(; item[idx] == ' '; idx++) - ; - auto eidx = idx; - for(; item[eidx] != '\n'; eidx++) - ; - string_view unit(item.substr(eidx - 2, 2)); - uint64_t value = atoll(item.data() + idx); - if(unit == "kB") - { - value *= 1024ULL; - } - else if(unit == "mB") - { - value *= 1024ULL * 1024; - } - else if(unit == "gB") - { - value *= 1024ULL * 1024 * 1024; - } - else if(unit == "tB") - { - value *= 1024ULL * 1024 * 1024 * 1024; - } - else if(unit == "pB") - { - value *= 1024ULL * 1024 * 1024 * 1024 * 1024; - } - else if(unit == "eB") - { - value *= 1024ULL * 1024 * 1024 * 1024 * 1024 * 1024; - } - else if(unit == "zB") - { - value *= 1024ULL * 1024 * 1024 * 1024 * 1024 * 1024 * 1024; - } - else if(unit == "yB") - { - value *= 1024ULL * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024; - } - else - { - return errc::illegal_byte_sequence; - } - return value; - }; process_memory_usage ret; // std::cerr << "Anon entries:"; for(auto &i : anon_entries) @@ -373,13 +456,13 @@ namespace utils { ret.total_address_space_in_use += size; ret.total_address_space_paged_in += rss; - ret.private_committed += size; - ret.private_paged_in += anonymous; + ret.private_committed += anonymous; if(lazyfree != (uint64_t) -1) { ret.total_address_space_paged_in -= lazyfree; - ret.private_paged_in -= lazyfree; + ret.private_committed -= lazyfree; } + ret.private_paged_in += rss; } // std::cerr << i << "\nSize = " << size << " Rss = " << rss << std::endl; } @@ -395,7 +478,7 @@ namespace utils ret.total_address_space_paged_in += rss; if(lazyfree != (uint64_t) -1) { - ret.total_address_space_paged_in -= lazyfree; + ret.total_address_space_in_use -= lazyfree; } } // std::cerr << i << "\nSize = " << size << " Rss = " << rss << std::endl; @@ -407,6 +490,7 @@ namespace utils return error_from_exception(); } #elif defined(__APPLE__) + (void) want; kern_return_t error; mach_msg_type_number_t outCount; task_vm_info_data_t vmInfo; |