1 // Copyright 2004-present Facebook. All Rights Reserved. 2 3 #include "SystemMetrics.h" 4 5 #if defined(IS_BSD) && defined(__APPLE__) 6 #include <mach/mach_init.h> 7 #include <mach/task.h> 8 #elif defined(IS_BSD) 9 #include <sys/resource.h> 10 #include <sys/time.h> 11 #include <sys/types.h> 12 #endif 13 14 namespace fbzmq { 15 16 /* Return RSS memory the process currently used from /proc/[pid]/status. 17 / The /proc is a pseudo-filesystem providing an API to kernel data 18 / structures. 19 */ 20 folly::Optional<size_t> getRSSMemBytes()21SystemMetrics::getRSSMemBytes() { 22 #if !defined(IS_BSD) 23 folly::Optional<size_t> rss{folly::none}; 24 // match the line like: "VmRSS: 9028 kB" 25 std::regex rssRegex("VmRSS:\\s+(\\d+)\\s+(\\w+)"); 26 std::smatch rssMatched; 27 std::string line; 28 std::ifstream input; 29 try { 30 // "/proc/self/" allows a process to look at itself without knowing the PID. 31 std::ifstream input("/proc/self/status"); 32 if (input.is_open()) { 33 while (std::getline(input, line)) { 34 if (std::regex_search(line, rssMatched, rssRegex) && 35 rssMatched[2] == "kB") { 36 rss = std::stoull(rssMatched[1]) * 1024; 37 break; 38 } 39 } 40 } 41 } catch (const std::exception& ex) { 42 LOG(ERROR) 43 << "Fail to read the \"/proc/self/status\" of current process to get the memory usage: " 44 << ex.what(); 45 } 46 return rss; 47 #elif !defined(__APPLE__) 48 struct rusage rusage; 49 getrusage(RUSAGE_SELF, &rusage); 50 return (size_t)(rusage.ru_maxrss * 1024); 51 #else 52 struct task_basic_info t_info; 53 mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT; 54 task_info( 55 current_task(), TASK_BASIC_INFO, (task_info_t)&t_info, &t_info_count); 56 return t_info.resident_size; 57 #endif 58 } 59 60 /* Return CPU% the process used 61 / This need to be called twice to get the time difference 62 / and calculate the CPU%. 63 / 64 / It will return folly::none when: 65 / 1. first time query 66 / 2. get invalid time: 67 / - previous timestamp > current timestamp 68 / - preivous total used time > current total used time 69 */ 70 folly::Optional<double> getCPUpercentage()71SystemMetrics::getCPUpercentage() { 72 struct rusage usage; 73 getrusage(RUSAGE_SELF, &usage); 74 75 ProcCpuTime nowCpuTime(usage); 76 folly::Optional<double> cpuPct{folly::none}; 77 78 // calculate the CPU% = (process time diff) / (time elapsed) * 100 79 if (prevCpuTime.timestamp != 0 && // has cached before 80 nowCpuTime.timestamp > prevCpuTime.timestamp && 81 nowCpuTime.totalTime > prevCpuTime.totalTime) { 82 uint64_t timestampDiff = nowCpuTime.timestamp - prevCpuTime.timestamp; 83 uint64_t procTimeDiff = nowCpuTime.totalTime - prevCpuTime.totalTime; 84 cpuPct = ((double)procTimeDiff / (double)timestampDiff) * 100; 85 } 86 87 // update the cache for next CPU% update 88 prevCpuTime = nowCpuTime; 89 90 return cpuPct; 91 } 92 93 // get current timestamp 94 uint64_t getCurrentNanoTime()95SystemMetrics::getCurrentNanoTime() { 96 return std::chrono::duration_cast<std::chrono::nanoseconds>( 97 std::chrono::steady_clock::now().time_since_epoch()) 98 .count(); 99 } 100 101 } // namespace fbzmq 102