statistics.hpp
1 
5 #pragma once
6 #include <cstddef>
7 #include <functional>
8 #include <map>
9 #include <mutex>
10 #include <string>
11 #include <utility>
12 
13 #include <rapidsmpf/rmm_resource_adaptor.hpp>
14 #include <rapidsmpf/utils.hpp>
15 
16 namespace rapidsmpf {
17 
18 
23 class Statistics {
24  public:
31  Statistics(bool enabled = true);
32 
43 
44  ~Statistics() noexcept = default;
45  Statistics(Statistics const&) = delete;
46  Statistics& operator=(Statistics const&) = delete;
47 
56  static std::shared_ptr<Statistics> disabled();
57 
63  Statistics(Statistics&& o) noexcept
64  : enabled_(o.enabled_), stats_{std::move(o.stats_)} {}
65 
72  Statistics& operator=(Statistics&& o) noexcept {
73  enabled_ = o.enabled_;
74  stats_ = std::move(o.stats_);
75  return *this;
76  }
77 
83  bool enabled() const noexcept {
84  return enabled_;
85  }
86 
93  std::string report(std::string const& header = "Statistics:") const;
94 
101  using Formatter = std::function<void(std::ostream&, std::size_t, double)>;
102 
112  static void FormatterDefault(std::ostream& os, std::size_t count, double val);
113 
117  class Stat {
118  public:
124  Stat(Formatter formatter) : formatter_{std::move(formatter)} {}
125 
132  bool operator==(Stat const& o) const noexcept {
133  return count_ == o.count() && value_ == o.value();
134  }
135 
144  double add(double value) {
145  ++count_;
146  return value_ += value;
147  }
148 
154  [[nodiscard]] std::size_t count() const noexcept {
155  return count_;
156  }
157 
163  [[nodiscard]] double value() const noexcept {
164  return value_;
165  }
166 
172  [[nodiscard]] Formatter const& formatter() const noexcept {
173  return formatter_;
174  }
175 
176  private:
177  std::size_t count_{0};
178  double value_{0};
179  Formatter formatter_;
180  };
181 
188  Stat get_stat(std::string const& name) const;
189 
200  double add_stat(
201  std::string const& name,
202  double value,
203  Formatter const& formatter = FormatterDefault
204  );
205 
215  std::size_t add_bytes_stat(std::string const& name, std::size_t nbytes);
216 
226  Duration add_duration_stat(std::string const& name, Duration seconds);
227 
233  std::vector<std::string> list_stat_names() const;
234 
240  void clear();
241 
248 
252  struct MemoryRecord {
254  std::int64_t global_peak{0};
255  std::uint64_t num_calls{0};
256  };
257 
264  public:
268  MemoryRecorder() = default;
269 
277  MemoryRecorder(Statistics* stats, RmmResourceAdaptor* mr, std::string name);
278 
285 
287  MemoryRecorder(MemoryRecorder const&) = delete;
288  MemoryRecorder& operator=(MemoryRecorder const&) = delete;
289  MemoryRecorder(MemoryRecorder&&) = delete;
290  MemoryRecorder& operator=(MemoryRecorder&&) = delete;
291 
292  private:
293  Statistics* stats_{nullptr};
294  RmmResourceAdaptor* mr_{nullptr};
295  std::string name_;
296  ScopedMemoryRecord main_record_;
297  };
298 
308 
314  std::unordered_map<std::string, MemoryRecord> const& get_memory_records() const;
315 
316  private:
317  mutable std::mutex mutex_;
318  bool enabled_;
319  std::map<std::string, Stat> stats_;
320  std::unordered_map<std::string, MemoryRecord> memory_records_;
321  RmmResourceAdaptor* mr_;
322 };
323 
347 #define RAPIDSMPF_MEMORY_PROFILE(...) \
348  RAPIDSMPF_OVERLOAD_BY_ARG_COUNT( \
349  __VA_ARGS__, RAPIDSMPF_MEMORY_PROFILE_2, RAPIDSMPF_MEMORY_PROFILE_1 \
350  ) \
351  (__VA_ARGS__)
352 
353 // Version with default function name (__func__)
354 #define RAPIDSMPF_MEMORY_PROFILE_1(stats) RAPIDSMPF_MEMORY_PROFILE_2(stats, __func__)
355 
356 // Version with custom function name
357 #define RAPIDSMPF_MEMORY_PROFILE_2(stats, funcname) \
358  auto const RAPIDSMPF_CONCAT(_rapidsmpf_memory_recorder_, __LINE__) = \
359  ((rapidsmpf::detail::to_pointer(stats) \
360  && rapidsmpf::detail::to_pointer(stats) -> is_memory_profiling_enabled()) \
361  ? rapidsmpf::detail::to_pointer(stats)->create_memory_recorder( \
362  std::string(__FILE__) + ":" + RAPIDSMPF_STRINGIFY(__LINE__) + "(" \
363  + std::string(funcname) + ")" \
364  ) \
365  : rapidsmpf::Statistics::MemoryRecorder{})
366 
367 } // namespace rapidsmpf
A RMM memory resource adaptor tailored to RapidsMPF.
RAII-style object for scoped memory usage tracking.
Definition: statistics.hpp:263
MemoryRecorder(Statistics *stats, RmmResourceAdaptor *mr, std::string name)
Constructs an active MemoryRecorder.
MemoryRecorder(MemoryRecorder const &)=delete
Deleted copy and move constructors/assignments.
MemoryRecorder()=default
Constructs a no-op MemoryRecorder (disabled state).
Represents a single tracked statistic.
Definition: statistics.hpp:117
Formatter const & formatter() const noexcept
Returns the formatter used by this statistic.
Definition: statistics.hpp:172
std::size_t count() const noexcept
Returns the number of updates applied to this statistic.
Definition: statistics.hpp:154
Stat(Formatter formatter)
Constructs a Stat with a specified formatter.
Definition: statistics.hpp:124
double add(double value)
Adds a value to this statistic.
Definition: statistics.hpp:144
double value() const noexcept
Returns the total accumulated value.
Definition: statistics.hpp:163
bool operator==(Stat const &o) const noexcept
Equality operator for Stat objects.
Definition: statistics.hpp:132
Track statistics across rapidsmpf operations.
Definition: statistics.hpp:23
std::string report(std::string const &header="Statistics:") const
Generates a formatted report of all collected statistics.
bool is_memory_profiling_enabled() const
Checks whether memory profiling is enabled.
Stat get_stat(std::string const &name) const
Retrieves a statistic by name.
double add_stat(std::string const &name, double value, Formatter const &formatter=FormatterDefault)
Adds a numeric value to the named statistic.
void clear()
Clears all statistics.
MemoryRecorder create_memory_recorder(std::string name)
Creates a scoped memory recorder for the given name.
static std::shared_ptr< Statistics > disabled()
Returns a shared pointer to a disabled (no-op) Statistics instance.
Statistics(RmmResourceAdaptor *mr)
Constructs a Statistics object with memory profiling enabled.
std::vector< std::string > list_stat_names() const
Get the names of all statistics.
Statistics(bool enabled=true)
Constructs a Statistics object without memory profiling.
static void FormatterDefault(std::ostream &os, std::size_t count, double val)
Default formatter for statistics output (implements Formatter).
std::size_t add_bytes_stat(std::string const &name, std::size_t nbytes)
Adds a byte count to the named statistic.
Duration add_duration_stat(std::string const &name, Duration seconds)
Adds a duration to the named statistic.
bool enabled() const noexcept
Checks if statistics tracking is enabled.
Definition: statistics.hpp:83
Statistics & operator=(Statistics &&o) noexcept
Move assignment operator.
Definition: statistics.hpp:72
std::function< void(std::ostream &, std::size_t, double)> Formatter
Type alias for a statistics formatting function.
Definition: statistics.hpp:101
std::unordered_map< std::string, MemoryRecord > const & get_memory_records() const
Retrieves all memory profiling records stored by this instance.
Memory statistics for a specific scope.
Holds memory profiling information for a named scope.
Definition: statistics.hpp:252
std::int64_t global_peak
Peak global memory usage during the scope.
Definition: statistics.hpp:254
ScopedMemoryRecord scoped
Scoped memory stats.
Definition: statistics.hpp:253
std::uint64_t num_calls
Number of times the scope was invoked.
Definition: statistics.hpp:255