8#ifndef INCLUDED_SDSL_MEMORY_TRACKING
9#define INCLUDED_SDSL_MEMORY_TRACKING
61 if (n <= std::numeric_limits<std::size_t>::max() /
sizeof(T))
63 size_t s = n *
sizeof(T);
64 if (
auto ptr = std::malloc(s))
67 return static_cast<T *
>(ptr);
70 throw std::bad_alloc();
74 std::size_t s = n *
sizeof(T);
80template <
typename T,
typename U>
86template <
typename T,
typename U>
96 std::atomic_flag m_slock;
105 while (m_slock.test_and_set(std::memory_order_acquire))
111 m_slock.clear(std::memory_order_release);
122 typedef std::map<std::string, ram_fs::content_type>
mss_type;
140 using timer = std::chrono::high_resolution_clock;
148 using timer = std::chrono::high_resolution_clock;
157 if (a.
allocations.size() && this->allocations.size())
159 if (this->allocations[0].timestamp == a.
allocations[0].timestamp)
161 return this->allocations.back().timestamp < a.
allocations.back().timestamp;
165 return this->allocations[0].timestamp < a.
allocations[0].timestamp;
174 using timer = std::chrono::high_resolution_clock;
191template <format_type F>
197 using timer = std::chrono::high_resolution_clock;
207 auto & m = *(the_monitor().m_tracker);
208 std::lock_guard<spin_lock> lock(m.spinlock);
209 m.event_stack.emplace(name, usage);
216 auto & m = *(the_monitor().m_tracker);
217 std::lock_guard<spin_lock> lock(m.spinlock);
218 auto & cur = m.event_stack.top();
219 auto cur_time = timer::now();
220 cur.allocations.emplace_back(cur_time, m.current_usage);
221 m.completed_events.emplace_back(std::move(cur));
225 if (!m.event_stack.empty())
227 if (m.event_stack.top().allocations.size())
229 auto last_usage = m.event_stack.top().allocations.back().usage;
230 m.event_stack.top().allocations.emplace_back(cur_time, last_usage);
257 memory_monitor(memory_monitor
const &) =
delete;
258 memory_monitor & operator=(memory_monitor
const &) =
delete;
260 static memory_monitor & the_monitor()
262 static memory_monitor m;
269 auto & m = *(the_monitor().m_tracker);
270 m.log_granularity = ms;
274 auto & m = *(the_monitor().m_tracker);
276 for (
auto events : m.completed_events)
278 for (
auto alloc : events.allocations)
280 if (max < alloc.usage)
291 return *(the_monitor().m_ram_fs);
296 auto & m = *(the_monitor().m_tracker);
297 m.track_usage =
true;
299 if (m.completed_events.size())
301 m.completed_events.clear();
303 while (m.event_stack.size())
307 m.start_log = timer::now();
309 m.last_event = m.start_log;
310 m.event_stack.emplace(
"unknown", 0);
314 auto & m = *(the_monitor().m_tracker);
315 while (!m.event_stack.empty())
317 m.completed_events.emplace_back(std::move(m.event_stack.top()));
320 m.track_usage =
false;
324 auto & m = *(the_monitor().m_tracker);
327 std::lock_guard<spin_lock> lock(m.spinlock);
328 auto cur = timer::now();
329 if (m.last_event + m.log_granularity < cur)
331 m.event_stack.top().allocations.emplace_back(cur, m.current_usage);
332 m.current_usage = m.current_usage + delta;
333 m.event_stack.top().allocations.emplace_back(cur, m.current_usage);
338 if (m.event_stack.top().allocations.size())
340 m.current_usage = m.current_usage + delta;
341 m.event_stack.top().allocations.back().usage = m.current_usage;
342 m.event_stack.top().allocations.back().timestamp = cur;
350 auto & m = *(the_monitor().m_tracker);
358 template <format_type F>
361 write_mem_log<F>(out, *(the_monitor().m_tracker));
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(std::string const &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 write_mem_log(std::ostream &out, tracker_storage const &m)
void memory_monitor_record(int64_t)
bool operator==(track_allocator< T > const &, track_allocator< U > const &)
bool operator!=(track_allocator< T > const &a, track_allocator< U > const &b)
timer::time_point created
mm_event_proxy(std::string const &name, int64_t usage, bool a)
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<(mm_event const &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
track_allocator(track_allocator< U > const &)
T * allocate(std::size_t n)
void deallocate(T *ptr, std::size_t n)
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