From 560a3582ccfd15f3602ae9a7ebfca008dce9cb9f Mon Sep 17 00:00:00 2001 From: kishorenc Date: Thu, 23 Jul 2020 22:22:39 +0530 Subject: [PATCH] Fetch memory metrics from jemalloc. --- include/system_metrics.h | 23 +++++++++---------- src/system_metrics.cpp | 48 +++++++++++++++++++++++++++++++++++----- 2 files changed, 54 insertions(+), 17 deletions(-) diff --git a/include/system_metrics.h b/include/system_metrics.h index 6ea58dee..91bac17c 100644 --- a/include/system_metrics.h +++ b/include/system_metrics.h @@ -2,6 +2,7 @@ #include #include #include +#include #include "json.hpp" const int NUM_CPU_STATES = 10; @@ -66,24 +67,22 @@ private: float active_percentage = 100.f * (active_time / total_time); float idle_percentage = 100.f * (idle_time / total_time); - std::stringstream active_ss; - active_ss.setf(std::ios::fixed, std::ios::floatfield); - active_ss.precision(2); - active_ss << active_percentage; - stat.active = active_ss.str(); - - std::stringstream idle_ss; - idle_ss.setf(std::ios::fixed, std::ios::floatfield); - idle_ss.precision(2); - idle_ss << idle_percentage; - stat.idle = idle_ss.str(); - + stat.active = format_dp(active_percentage); + stat.idle = format_dp(idle_percentage); stats.push_back(stat); } return stats; } + std::string format_dp(float value) const { + std::stringstream active_ss; + active_ss.setf(std::ios::fixed, std::ios::floatfield); + active_ss.precision(2); + active_ss << value; + return active_ss.str(); + } + void read_cpu_data(std::vector &entries) { std::ifstream stat_file("/proc/stat"); diff --git a/src/system_metrics.cpp b/src/system_metrics.cpp index 3f57d329..c7fabd82 100644 --- a/src/system_metrics.cpp +++ b/src/system_metrics.cpp @@ -14,6 +14,8 @@ #include #endif +#include "jemalloc.h" + void SystemMetrics::get(const std::string &data_dir_path, nlohmann::json &result) { // DISK METRICS struct statvfs st{}; @@ -25,15 +27,51 @@ void SystemMetrics::get(const std::string &data_dir_path, nlohmann::json &result // MEMORY METRICS + size_t sz, active, allocated; + + /* + stats.active: + Returns the total number of bytes in active pages allocated by the application. + + stats.allocated + Returns the total number of bytes allocated by the application. Will be larger than active. + + active/allocated == fragmentation ratio. + */ + +#ifdef __APPLE__ + je_mallctl("thread.tcache.flush", nullptr, nullptr, nullptr, 0); + je_mallctl("stats.active", &active, &sz, nullptr, 0); + je_mallctl("stats.allocated", &allocated, &sz, nullptr, 0); +#elif __linux__ + mallctl("thread.tcache.flush", nullptr, nullptr, nullptr, 0); + mallctl("stats.active", &active, &sz, nullptr, 0); + mallctl("stats.allocated", &allocated, &sz, nullptr, 0); +#else + active = allocated = 0; +#endif + + if(active != 0 && allocated != 0) { + // bytes allocated by allocator (jemalloc) + result["typesense_memory_used_bytes"] = std::to_string(allocated); + result["typesense_memory_active_bytes"] = std::to_string(active); + + // Defragmentation ratio is calculated very similar to Redis: + // https://github.com/redis/redis/blob/d6180c8c8674ffdae3d6efa5f946d85fe9163464/src/defrag.c#L900 + std::string frag_percent = format_dp(((float)active / allocated)*100 - 100); + result["fragmentation_percent"] = frag_percent; + } + rusage r_usage; getrusage(RUSAGE_SELF, &r_usage); + // Bytes allocated by OS (resident set size) and is the number reported by tools such as htop. // `ru_maxrss` is in bytes on OSX but in kilobytes on Linux - #ifdef __APPLE__ - result["typesense_memory_used_bytes"] = std::to_string(r_usage.ru_maxrss); - #elif __linux__ - result["typesense_memory_used_bytes"] = std::to_string(r_usage.ru_maxrss * 1000); - #endif +#ifdef __APPLE__ + result["typesense_memory_used_rss_bytes"] = std::to_string(r_usage.ru_maxrss); +#elif __linux__ + result["typesense_memory_used_rss_bytes"] = std::to_string(r_usage.ru_maxrss * 1000); +#endif uint64_t memory_available_bytes = 0; uint64_t memory_total_bytes = 0;