Network System 0.1.1
High-performance modular networking library for scalable client-server applications
Loading...
Searching...
No Matches
memory_profiler.cpp
Go to the documentation of this file.
1// BSD 3-Clause License
2// Copyright (c) 2021-2025, 🍀☀🌕🌥 🌊
3// See the LICENSE file in the project root for full license information.
4
5#include "memory_profiler.h"
7
8#include <sstream>
9#include <iomanip>
10
11#if defined(__APPLE__)
12#include <mach/mach.h>
13#elif defined(__linux__)
14#include <cstdio>
15#include <unistd.h>
16#elif defined(_WIN32)
17#include <windows.h>
18#include <psapi.h>
19#pragma comment(lib, "psapi.lib")
20#endif
21
22namespace kcenon::network::utils {
23
28
30
31void memory_profiler::start(std::chrono::milliseconds interval) {
32#ifndef NETWORK_ENABLE_MEMORY_PROFILER
33 (void)interval;
34 return; // profiling disabled
35#else
36 if (running_.exchange(true)) return;
37 sampling_interval_ = interval;
39#endif
40}
41
43#ifdef NETWORK_ENABLE_MEMORY_PROFILER
44 running_.store(false);
45#endif
46}
47
49 memory_snapshot snap;
50 snap.timestamp = std::chrono::system_clock::now();
51 std::uint64_t rss=0, vms=0;
52 query_process_memory(rss, vms);
53 snap.resident_bytes = rss;
54 snap.virtual_bytes = vms;
55
56 std::lock_guard<std::mutex> lock(mutex_);
57 history_.push_back(snap);
58 if (history_.size() > max_history_) {
59 history_.erase(history_.begin(), history_.begin() + (history_.size() - max_history_));
60 }
61 return snap;
62}
63
64std::vector<memory_snapshot> memory_profiler::get_history(std::size_t max_count) const {
65 std::lock_guard<std::mutex> lock(mutex_);
66 if (max_count >= history_.size()) return history_;
67 return std::vector<memory_snapshot>(history_.end() - max_count, history_.end());
68}
69
71 std::lock_guard<std::mutex> lock(mutex_);
72 history_.clear();
73}
74
75std::string memory_profiler::to_tsv() const {
76 std::ostringstream oss;
77 std::lock_guard<std::mutex> lock(mutex_);
78 for (const auto& s : history_) {
79 auto t = std::chrono::system_clock::to_time_t(s.timestamp);
80 oss << std::put_time(std::localtime(&t), "%Y-%m-%d %H:%M:%S")
81 << '\t' << s.resident_bytes
82 << '\t' << s.virtual_bytes
83 << '\n';
84 }
85 return oss.str();
86}
87
89#ifdef NETWORK_ENABLE_MEMORY_PROFILER
90 if (!running_.load()) return;
91
94 [this]() {
95 if (running_.load()) {
96 snapshot();
98 }
99 },
101#endif
102}
103
104bool memory_profiler::query_process_memory(std::uint64_t& rss, std::uint64_t& vms) {
105#if defined(__APPLE__)
106 task_basic_info_data_t info;
107 mach_msg_type_number_t count = TASK_BASIC_INFO_COUNT;
108 if (task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &count) != KERN_SUCCESS) {
109 return false;
110 }
111 rss = static_cast<std::uint64_t>(info.resident_size);
112 vms = static_cast<std::uint64_t>(info.virtual_size);
113 return true;
114#elif defined(__linux__)
115 FILE* f = std::fopen("/proc/self/statm", "r");
116 if (!f) return false;
117 long pages_res=0, pages_total=0;
118 int rc = std::fscanf(f, "%ld %ld", &pages_total, &pages_res);
119 std::fclose(f);
120 if (rc != 2) return false;
121 long page_size = sysconf(_SC_PAGESIZE);
122 vms = static_cast<std::uint64_t>(pages_total) * static_cast<std::uint64_t>(page_size);
123 rss = static_cast<std::uint64_t>(pages_res) * static_cast<std::uint64_t>(page_size);
124 return true;
125#elif defined(_WIN32)
126 PROCESS_MEMORY_COUNTERS_EX pmc{};
127 if (GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc))) {
128 rss = static_cast<std::uint64_t>(pmc.WorkingSetSize);
129 vms = static_cast<std::uint64_t>(pmc.PrivateUsage);
130 return true;
131 }
132 return false;
133#else
134 // Unknown platform
135 rss = vms = 0;
136 return false;
137#endif
138}
139
140} // namespace kcenon::network::utils
141
std::future< void > submit_delayed_task(std::function< void()> task, std::chrono::milliseconds delay)
Submit a task with delay.
static thread_integration_manager & instance()
Get the singleton instance.
static bool query_process_memory(std::uint64_t &rss, std::uint64_t &vms)
std::vector< memory_snapshot > get_history(std::size_t max_count=256) const
std::chrono::milliseconds sampling_interval_
std::vector< memory_snapshot > history_
void start(std::chrono::milliseconds interval=std::chrono::milliseconds{1000})
Lightweight, cross-platform process memory profiler (optional)
Utility components for network_system.
std::chrono::system_clock::time_point timestamp
Thread system integration interface for network_system.