8#ifndef INCLUDED_SDSL_MEMORY_TRACKING
9#define INCLUDED_SDSL_MEMORY_TRACKING
65 if (n <= std::numeric_limits<std::size_t>::max() /
sizeof(T))
67 size_t s = n *
sizeof(T);
68 if (
auto ptr = std::malloc(s))
71 return static_cast<T *
>(ptr);
74 throw std::bad_alloc();
78 std::size_t s = n *
sizeof(T);
84template <
typename T,
typename U>
90template <
typename T,
typename U>
100 std::atomic_flag m_slock;
106 while (m_slock.test_and_set(std::memory_order_acquire))
110 void unlock() { m_slock.clear(std::memory_order_release); };
120 typedef std::map<std::string, ram_fs::content_type>
mss_type;
134 using timer = std::chrono::high_resolution_clock;
144 using timer = std::chrono::high_resolution_clock;
154 if (a.
allocations.size() && this->allocations.size())
156 if (this->allocations[0].timestamp == a.
allocations[0].timestamp)
158 return this->allocations.back().timestamp < a.
allocations.back().timestamp;
162 return this->allocations[0].timestamp < a.
allocations[0].timestamp;
171 using timer = std::chrono::high_resolution_clock;
186template <format_type F>
192 using timer = std::chrono::high_resolution_clock;
203 auto & m = *(the_monitor().m_tracker);
204 std::lock_guard<spin_lock> lock(m.spinlock);
205 m.event_stack.emplace(name, usage);
212 auto & m = *(the_monitor().m_tracker);
213 std::lock_guard<spin_lock> lock(m.spinlock);
214 auto & cur = m.event_stack.top();
215 auto cur_time = timer::now();
216 cur.allocations.emplace_back(cur_time, m.current_usage);
217 m.completed_events.emplace_back(std::move(cur));
221 if (!m.event_stack.empty())
223 if (m.event_stack.top().allocations.size())
225 auto last_usage = m.event_stack.top().allocations.back().usage;
226 m.event_stack.top().allocations.emplace_back(cur_time, last_usage);
250 memory_monitor(
const memory_monitor &) =
delete;
251 memory_monitor & operator=(
const memory_monitor &) =
delete;
253 static memory_monitor & the_monitor()
255 static memory_monitor m;
262 auto & m = *(the_monitor().m_tracker);
263 m.log_granularity = ms;
267 auto & m = *(the_monitor().m_tracker);
269 for (
auto events : m.completed_events)
271 for (
auto alloc : events.allocations)
273 if (max < alloc.usage) { max = alloc.usage; }
283 auto & m = *(the_monitor().m_tracker);
284 m.track_usage =
true;
286 if (m.completed_events.size()) { m.completed_events.clear(); }
287 while (m.event_stack.size()) { m.event_stack.pop(); }
288 m.start_log = timer::now();
290 m.last_event = m.start_log;
291 m.event_stack.emplace(
"unknown", 0);
295 auto & m = *(the_monitor().m_tracker);
296 while (!m.event_stack.empty())
298 m.completed_events.emplace_back(std::move(m.event_stack.top()));
301 m.track_usage =
false;
305 auto & m = *(the_monitor().m_tracker);
308 std::lock_guard<spin_lock> lock(m.spinlock);
309 auto cur = timer::now();
310 if (m.last_event + m.log_granularity < cur)
312 m.event_stack.top().allocations.emplace_back(cur, m.current_usage);
313 m.current_usage = m.current_usage + delta;
314 m.event_stack.top().allocations.emplace_back(cur, m.current_usage);
319 if (m.event_stack.top().allocations.size())
321 m.current_usage = m.current_usage + delta;
322 m.event_stack.top().allocations.back().usage = m.current_usage;
323 m.event_stack.top().allocations.back().timestamp = cur;
331 auto & m = *(the_monitor().m_tracker);
332 if (m.track_usage) {
return mm_event_proxy(name, m.current_usage,
true); }
336 template <format_type F>
339 write_mem_log<F>(out, *(the_monitor().m_tracker));
bits.hpp contains the sdsl::bits class.
static void granularity(std::chrono::milliseconds ms)
std::chrono::high_resolution_clock timer
static ramfs_storage & ram_fs()
static void record(int64_t delta)
static mm_event_proxy event(const std::string &name)
static void write_memory_log(std::ostream &out)
std::vector< char, track_allocator< char > > content_type
Namespace for the succinct data structure library.
void memory_monitor_record(int64_t)
bool operator==(const track_allocator< T > &, const track_allocator< U > &)
bool operator!=(const track_allocator< T > &a, const track_allocator< U > &b)
void write_mem_log(std::ostream &out, const tracker_storage &m)
mm_event_proxy(const std::string &name, int64_t usage, bool a)
timer::time_point created
std::chrono::high_resolution_clock timer
mm_alloc(timer::time_point t, int64_t u)
timer::time_point timestamp
std::vector< mm_alloc > allocations
std::chrono::high_resolution_clock timer
bool operator<(const mm_event &a) const
mm_event(std::string n, int64_t usage)
std::recursive_mutex m_rlock
std::map< int, std::string > mis_type
std::map< std::string, ram_fs::content_type > mss_type
track_allocator()=default
T * allocate(std::size_t n)
void deallocate(T *ptr, std::size_t n)
track_allocator(const track_allocator< U > &)
std::vector< mm_event > completed_events
std::stack< mm_event > event_stack
timer::time_point start_log
std::chrono::milliseconds log_granularity
std::chrono::high_resolution_clock timer
timer::time_point last_event