diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f664e0d..9aab4d8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -65,9 +65,6 @@ jobs: - name: Checkout repository uses: actions/checkout@v7 - - name: Install Doxygen - uses: ssciwr/doxygen-install@v2 - - name: Configure cmake shell: bash run: cmake -B build -DCMAKE_BUILD_TYPE=Debug -Dndtbl_BUILD_TESTING=ON -Dndtbl_BUILD_DOCS=OFF -Dndtbl_ENABLE_MMAP=${{ matrix.mmap }} @@ -95,9 +92,6 @@ jobs: run: | sudo apt-get install -y lcov - - name: Install Doxygen - uses: ssciwr/doxygen-install@v2 - - name: Configure cmake shell: bash run: | diff --git a/CITATION.cff b/CITATION.cff index 62477a6..2bb2f84 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -5,6 +5,7 @@ abstract: "Multidimensional table lookup library for C++." authors: - family-names: Isensee given-names: Thomas + affiliation: "Scientific Software Center (SSC), Interdisciplinary Center for Scientific Computing (IWR), Heidelberg University, Germany" orcid: "https://orcid.org/0000-0002-7242-4529" keywords: - "table lookup" diff --git a/CMakeLists.txt b/CMakeLists.txt index 3def6b7..3d62472 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,7 +70,7 @@ target_sources(ndtbl include/ndtbl/detail/mapped_payload.hpp ) -# Compile flag for enabling mmap support +# Compile flags for enabling mmap support and related features target_compile_definitions(ndtbl INTERFACE NDTBL_ENABLE_MMAP=$ diff --git a/include/ndtbl/detail/mapped_payload.hpp b/include/ndtbl/detail/mapped_payload.hpp index 33c2903..1caefde 100644 --- a/include/ndtbl/detail/mapped_payload.hpp +++ b/include/ndtbl/detail/mapped_payload.hpp @@ -18,16 +18,14 @@ #include "ndtbl/exceptions.hpp" #include + +#if NDTBL_ENABLE_MMAP +#include #include -#include +#include #include #include #include -#include - -#if NDTBL_ENABLE_MMAP || NDTBL_ENABLE_MMAP_DIAGNOSTICS -#include -#include #include #include @@ -35,6 +33,14 @@ #include #endif +#if NDTBL_ENABLE_MMAP_DIAGNOSTICS +#include +#include +#include +#include +#include +#endif + #if NDTBL_ENABLE_MMAP_DIAGNOSTICS #if !NDTBL_ENABLE_MMAP #error "NDTBL_ENABLE_MMAP_DIAGNOSTICS requires NDTBL_ENABLE_MMAP" @@ -59,10 +65,10 @@ namespace detail { inline residency_info unavailable_residency() { - return residency_info{ false, 0, 0, 0, 0, 0.0 }; + return residency_info{}; } -#if NDTBL_ENABLE_MMAP || NDTBL_ENABLE_MMAP_DIAGNOSTICS +#if NDTBL_ENABLE_MMAP inline std::string system_error_message(const std::string& prefix) @@ -74,11 +80,120 @@ system_error_message(const std::string& prefix) #if NDTBL_ENABLE_MMAP_DIAGNOSTICS +inline bool +parse_smaps_header(const std::string& line, + std::uintptr_t& start, + std::uintptr_t& end) +{ + unsigned long long parsed_start = 0; + unsigned long long parsed_end = 0; + if (std::sscanf(line.c_str(), "%llx-%llx", &parsed_start, &parsed_end) != 2) { + return false; + } + + start = static_cast(parsed_start); + end = static_cast(parsed_end); + return true; +} + +inline std::size_t +parse_smaps_kib(const std::string& line, const char* key) +{ + const std::string key_string(key); + if (line.compare(0, key_string.size(), key_string) != 0) { + return 0; + } + + std::istringstream is(line.substr(key_string.size())); + std::size_t value_kib = 0; + is >> value_kib; + return value_kib; +} + +inline void +query_smaps_mapping(const void* address, residency_info& info) +{ + std::ifstream smaps("/proc/self/smaps"); + if (!smaps.is_open()) { + return; + } + + const std::uintptr_t target = reinterpret_cast(address); + std::uintptr_t mapping_start = 0; + std::uintptr_t mapping_end = 0; + bool in_target_mapping = false; + std::string line; + + while (std::getline(smaps, line)) { + std::uintptr_t header_start = 0; + std::uintptr_t header_end = 0; + if (parse_smaps_header(line, header_start, header_end)) { + if (in_target_mapping) { + return; + } + + in_target_mapping = header_start <= target && target < header_end; + if (in_target_mapping) { + mapping_start = header_start; + mapping_end = header_end; + info.smaps_available = true; + info.smaps_mapping_bytes = + static_cast(mapping_end - mapping_start); + } + continue; + } + + if (!in_target_mapping) { + continue; + } + + const std::size_t rss_kib = parse_smaps_kib(line, "Rss:"); + if (rss_kib != 0) { + info.smaps_rss_bytes = rss_kib * 1024; + continue; + } + + const std::size_t pss_kib = parse_smaps_kib(line, "Pss:"); + if (pss_kib != 0) { + info.smaps_pss_bytes = pss_kib * 1024; + continue; + } + + const std::size_t shared_clean_kib = parse_smaps_kib(line, "Shared_Clean:"); + if (shared_clean_kib != 0) { + info.smaps_shared_clean_bytes = shared_clean_kib * 1024; + continue; + } + + const std::size_t shared_dirty_kib = parse_smaps_kib(line, "Shared_Dirty:"); + if (shared_dirty_kib != 0) { + info.smaps_shared_dirty_bytes = shared_dirty_kib * 1024; + continue; + } + + const std::size_t private_clean_kib = + parse_smaps_kib(line, "Private_Clean:"); + if (private_clean_kib != 0) { + info.smaps_private_clean_bytes = private_clean_kib * 1024; + continue; + } + + const std::size_t private_dirty_kib = + parse_smaps_kib(line, "Private_Dirty:"); + if (private_dirty_kib != 0) { + info.smaps_private_dirty_bytes = private_dirty_kib * 1024; + continue; + } + } +} + inline residency_info query_residency(const void* address, std::size_t length) { if (length == 0) { - return residency_info{ true, 0, 0, 0, 0, 0.0 }; + residency_info info; + info.available = true; + return info; } if (address == nullptr) { throw std::invalid_argument("cannot query residency for a null payload"); @@ -117,13 +232,18 @@ query_residency(const void* address, std::size_t length) } } - return residency_info{ true, - page_size, - total_pages, - resident_pages, - resident_pages * page_size, - static_cast(resident_pages) / - static_cast(total_pages) }; + residency_info info; + info.available = true; + info.page_size = page_size; + info.total_pages = total_pages; + info.resident_pages = resident_pages; + info.resident_bytes = resident_pages * page_size; + info.resident_fraction = + static_cast(resident_pages) / static_cast(total_pages); + + query_smaps_mapping(address, info); + + return info; } #else diff --git a/include/ndtbl/diagnostics.hpp b/include/ndtbl/diagnostics.hpp index ccf9966..119f046 100644 --- a/include/ndtbl/diagnostics.hpp +++ b/include/ndtbl/diagnostics.hpp @@ -13,12 +13,21 @@ namespace ndtbl { */ struct residency_info { - bool available; - std::size_t page_size; - std::size_t total_pages; - std::size_t resident_pages; - std::size_t resident_bytes; - double resident_fraction; + bool available = false; + std::size_t page_size = 0; + std::size_t total_pages = 0; + std::size_t resident_pages = 0; + std::size_t resident_bytes = 0; + double resident_fraction = 0.0; + + bool smaps_available = false; + std::size_t smaps_mapping_bytes = 0; + std::size_t smaps_rss_bytes = 0; + std::size_t smaps_pss_bytes = 0; + std::size_t smaps_shared_clean_bytes = 0; + std::size_t smaps_shared_dirty_bytes = 0; + std::size_t smaps_private_clean_bytes = 0; + std::size_t smaps_private_dirty_bytes = 0; }; } // namespace ndtbl