Jlm
Statistics.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2017 Nico Reißmann <nico.reissmann@gmail.com>
3  * Copyright 2024 Håvard Krogstie <krogstie.havard@gmail.com>
4  * See COPYING for terms of redistribution.
5  */
6 
7 #ifndef JLM_UTIL_STATISTICS_HPP
8 #define JLM_UTIL_STATISTICS_HPP
9 
10 #include <jlm/util/file.hpp>
11 #include <jlm/util/HashSet.hpp>
12 #include <jlm/util/strfmt.hpp>
13 #include <jlm/util/time.hpp>
14 
15 #include <cstdint>
16 #include <list>
17 #include <memory>
18 #include <optional>
19 #include <string>
20 #include <unordered_map>
21 #include <variant>
22 #include <vector>
23 
24 namespace jlm::util
25 {
26 
31 {
32 public:
33  enum class Id
34  {
35  FirstEnumValue, // must always be the first enum value, used for iteration
36 
41  Annotation,
53  PullNodes,
54  PushNodes,
62 
63  LastEnumValue // must always be the last enum value, used for iteration
64  };
65 
66  using Measurement = std::variant<std::string, int64_t, uint64_t, double>;
67  // Lists are used instead of vectors to give stable references to members
68  using MeasurementList = std::list<std::pair<std::string, Measurement>>;
69  using TimerList = std::list<std::pair<std::string, util::Timer>>;
70 
71  virtual ~Statistics();
72 
73  Statistics(const Statistics::Id & statisticsId, util::FilePath sourceFile)
74  : StatisticsId_(statisticsId),
75  SourceFile_(std::move(sourceFile))
76  {}
77 
78  [[nodiscard]] Statistics::Id
79  GetId() const noexcept
80  {
81  return StatisticsId_;
82  }
83 
87  [[nodiscard]] std::string_view
88  GetName() const;
89 
93  [[nodiscard]] const util::FilePath &
94  GetSourceFile() const;
95 
106  [[nodiscard]] std::string
107  Serialize(char fieldSeparator, char nameValueSeparator) const;
108 
113  [[nodiscard]] bool
114  HasMeasurement(const std::string & name) const noexcept;
115 
120  [[nodiscard]] const Measurement &
121  GetMeasurement(const std::string & name) const;
122 
128  template<typename T>
129  [[nodiscard]] const T &
130  GetMeasurementValue(const std::string & name) const
131  {
132  const auto & measurement = GetMeasurement(name);
133  return std::get<T>(measurement);
134  }
135 
140  GetMeasurements() const;
141 
146  [[nodiscard]] bool
147  HasTimer(const std::string & name) const noexcept;
148 
154  [[nodiscard]] size_t
155  GetTimerElapsedNanoseconds(const std::string & name) const
156  {
157  return GetTimer(name).ns();
158  }
159 
164  GetTimers() const;
165 
166 protected:
172  template<typename T>
173  void
174  AddMeasurement(std::string name, T value)
175  {
176  JLM_ASSERT(!HasMeasurement(name));
177  Measurements_.emplace_back(std::make_pair(std::move(name), std::move(value)));
178  }
179 
185  util::Timer &
186  AddTimer(std::string name);
187 
193  [[nodiscard]] util::Timer &
194  GetTimer(const std::string & name);
195 
196  [[nodiscard]] const util::Timer &
197  GetTimer(const std::string & name) const;
198 
202  struct Label
203  {
204  static inline const char * FunctionNameLabel_ = "Function";
205 
206  static inline const char * NumCfgNodes = "#CfgNodes";
207 
208  static inline const char * NumThreeAddressCodes = "#ThreeAddressCodes";
209 
210  static inline const char * NumRvsdgNodes = "#RvsdgNodes";
211  static inline const char * NumRvsdgNodesBefore = "#RvsdgNodesBefore";
212  static inline const char * NumRvsdgNodesAfter = "#RvsdgNodesAfter";
213 
214  static inline const char * NumRvsdgInputsBefore = "#RvsdgInputsBefore";
215  static inline const char * NumRvsdgInputsAfter = "#RvsdgInputsAfter";
216 
217  inline static const char * NumPointsToGraphNodes = "#PointsToGraphNodes";
218  inline static const char * NumPointsToGraphAllocaNodes = "#PointsToGraphAllocaNodes";
219  inline static const char * NumPointsToGraphDeltaNodes = "#PointsToGraphDeltaNodes";
220  inline static const char * NumPointsToGraphImportNodes = "#PointsToGraphImportNodes";
221  inline static const char * NumPointsToGraphLambdaNodes = "#PointsToGraphLambdaNodes";
222  inline static const char * NumPointsToGraphMallocNodes = "#PointsToGraphMallocNodes";
223  inline static const char * NumPointsToGraphMemoryNodes = "#PointsToGraphMemoryNodes";
224  inline static const char * NumPointsToGraphRegisterNodes = "#PointsToGraphRegisterNodes";
225  inline static const char * NumPointsToGraphExternallyAvailableNodes =
226  "#PointsToGraphExternallyAvailableNodes";
228  "#PointsToGraphNodesTargetsAllExternallyAvailable";
229 
230  inline static const char * NumPointsToGraphExplicitEdges = "#PointsToGraphExplicitEdges";
231  inline static const char * NumPointsToGraphEdges = "#PointsToGraphEdges";
232 
233  inline static const char * NumLoopVariablesTotal = "#LoopVariablesTotal";
234  inline static const char * NumTotalRecurrences = "#TotalRecurrences";
235  inline static const char * NumConstantRecurrences = "#ConstantRecurrences";
236  inline static const char * NumFirstOrderRecurrences = "#FirstOrderRecurrences";
237  inline static const char * NumSecondOrderRecurrences = "#SecondOrderRecurrences";
238  inline static const char * NumThirdOrderRecurrences = "#ThirdOrderRecurrences";
239 
240  static inline const char * Timer = "Time";
241  };
242 
243 private:
246 
249 };
250 
255 {
256 public:
262  : Directory_("."),
263  ModuleName_("")
264  {}
265 
272  : DemandedStatistics_(std::move(demandedStatistics)),
273  Directory_("."),
274  ModuleName_("")
275  {}
276 
292  HashSet<Statistics::Id> demandedStatistics,
293  std::optional<FilePath> directory,
294  std::string moduleName)
295  : DemandedStatistics_(std::move(demandedStatistics)),
296  Directory_(std::move(directory)),
297  ModuleName_(std::move(moduleName))
298  {}
299 
304  void
306  {
307  DemandedStatistics_ = std::move(demandedStatistics);
308  }
309 
313  [[nodiscard]] size_t
314  NumDemandedStatistics() const noexcept
315  {
316  return DemandedStatistics_.Size();
317  }
318 
322  [[nodiscard]] const HashSet<Statistics::Id> &
323  GetDemandedStatistics() const noexcept
324  {
325  return DemandedStatistics_;
326  }
327 
333  [[nodiscard]] bool
334  isDemanded(Statistics::Id id) const noexcept
335  {
336  return DemandedStatistics_.Contains(id);
337  }
338 
343  [[nodiscard]] bool
344  HasOutputDirectory() const noexcept
345  {
346  return Directory_.has_value();
347  }
348 
352  [[nodiscard]] const FilePath &
353  GetOutputDirectory() const noexcept
354  {
355  JLM_ASSERT(Directory_.has_value());
356  return Directory_.value();
357  }
358 
365  [[nodiscard]] const FilePath &
366  GetOrCreateOutputDirectory() const noexcept
367  {
368  JLM_ASSERT(Directory_.has_value());
369  Directory_->CreateDirectory();
370  return Directory_.value();
371  }
372 
378  void
380  {
381  Directory_ = std::move(directory);
382  }
383 
387  [[nodiscard]] const std::string &
388  GetModuleName() const noexcept
389  {
390  return ModuleName_;
391  }
392 
396  void
397  SetModuleName(std::string moduleName)
398  {
399  ModuleName_ = std::move(moduleName);
400  }
401 
405  [[nodiscard]] const std::string &
406  GetUniqueString() const noexcept
407  {
408  return UniqueString_;
409  }
410 
415  void
416  SetUniqueString(std::string uniqueString)
417  {
418  UniqueString_ = std::move(uniqueString);
419  }
420 
421 private:
423  std::optional<FilePath> Directory_;
424  std::string ModuleName_;
426 };
427 
432 {
433  class StatisticsIterator final
434  {
435  public:
436  using iterator_category = std::forward_iterator_tag;
437  using value_type = const Statistics *;
438  using difference_type = std::ptrdiff_t;
439  using pointer = const Statistics **;
440  using reference = const Statistics *&;
441 
442  private:
444 
445  explicit StatisticsIterator(const std::vector<std::unique_ptr<Statistics>>::const_iterator & it)
446  : it_(it)
447  {}
448 
449  public:
450  [[nodiscard]] const Statistics *
451  GetStatistics() const noexcept
452  {
453  return it_->get();
454  }
455 
456  const Statistics &
457  operator*() const
458  {
459  JLM_ASSERT(GetStatistics() != nullptr);
460  return *GetStatistics();
461  }
462 
463  const Statistics *
464  operator->() const
465  {
466  return GetStatistics();
467  }
468 
471  {
472  ++it_;
473  return *this;
474  }
475 
478  {
479  StatisticsIterator tmp = *this;
480  ++*this;
481  return tmp;
482  }
483 
484  bool
485  operator==(const StatisticsIterator & other) const
486  {
487  return it_ == other.it_;
488  }
489 
490  bool
491  operator!=(const StatisticsIterator & other) const
492  {
493  return !operator==(other);
494  }
495 
496  private:
497  std::vector<std::unique_ptr<Statistics>>::const_iterator it_;
498  };
499 
500 public:
502 
504  {}
505 
507  : Settings_(std::move(settings))
508  {}
509 
511  GetSettings() const noexcept
512  {
513  return Settings_;
514  }
515 
517  CollectedStatistics() const noexcept
518  {
519  return { StatisticsIterator(CollectedStatistics_.begin()),
521  }
522 
523  [[nodiscard]] size_t
524  NumCollectedStatistics() const noexcept
525  {
526  return CollectedStatistics_.size();
527  }
528 
536  [[nodiscard]] bool
537  IsDemanded(Statistics::Id id) const noexcept
538  {
539  return GetSettings().isDemanded(id);
540  }
541 
549  [[nodiscard]] bool
550  IsDemanded(const Statistics & statistics) const noexcept
551  {
552  return IsDemanded(statistics.GetId());
553  }
554 
562  void
563  CollectDemandedStatistics(std::unique_ptr<Statistics> statistics)
564  {
565  if (IsDemanded(*statistics))
566  CollectedStatistics_.emplace_back(std::move(statistics));
567  }
568 
576  [[nodiscard]] std::unique_ptr<Statistics>
578  {
579  auto it = CollectedStatistics_.end();
580  while (it != CollectedStatistics_.begin())
581  {
582  it--;
583  if (it->get()->GetId() == id)
584  {
585  auto result = std::move(*it);
586  CollectedStatistics_.erase(it);
587  return result;
588  }
589  }
590  throw std::out_of_range("No Statistics with the given id has been collected");
591  }
592 
598  void
599  PrintStatistics();
600 
618  [[nodiscard]] File
619  createOutputFile(std::string fileNameSuffix, bool includeCount = false);
620 
621 private:
623  std::vector<std::unique_ptr<Statistics>> CollectedStatistics_;
624 
625  // Counter used to give unique file names to output files that share suffix
626  std::unordered_map<std::string, size_t> OutputFileCounter_;
627 };
628 
629 }
630 
631 #endif
std::size_t Size() const noexcept
Definition: HashSet.hpp:187
bool Contains(const ItemType &item) const noexcept
Definition: HashSet.hpp:150
void SetOutputDirectory(FilePath directory)
Definition: Statistics.hpp:379
size_t NumDemandedStatistics() const noexcept
Definition: Statistics.hpp:314
bool HasOutputDirectory() const noexcept
Definition: Statistics.hpp:344
std::optional< FilePath > Directory_
Definition: Statistics.hpp:423
void SetUniqueString(std::string uniqueString)
Definition: Statistics.hpp:416
void SetDemandedStatistics(HashSet< Statistics::Id > demandedStatistics)
Definition: Statistics.hpp:305
const std::string & GetUniqueString() const noexcept
Definition: Statistics.hpp:406
const HashSet< Statistics::Id > & GetDemandedStatistics() const noexcept
Definition: Statistics.hpp:323
HashSet< Statistics::Id > DemandedStatistics_
Definition: Statistics.hpp:422
StatisticsCollectorSettings(HashSet< Statistics::Id > demandedStatistics, std::optional< FilePath > directory, std::string moduleName)
Definition: Statistics.hpp:291
const FilePath & GetOutputDirectory() const noexcept
Definition: Statistics.hpp:353
void SetModuleName(std::string moduleName)
Definition: Statistics.hpp:397
const FilePath & GetOrCreateOutputDirectory() const noexcept
Definition: Statistics.hpp:366
bool isDemanded(Statistics::Id id) const noexcept
Checks if a statistics is demanded.
Definition: Statistics.hpp:334
const std::string & GetModuleName() const noexcept
Definition: Statistics.hpp:388
StatisticsCollectorSettings(HashSet< Statistics::Id > demandedStatistics)
Definition: Statistics.hpp:271
const Statistics * GetStatistics() const noexcept
Definition: Statistics.hpp:451
StatisticsIterator(const std::vector< std::unique_ptr< Statistics >>::const_iterator &it)
Definition: Statistics.hpp:445
bool operator!=(const StatisticsIterator &other) const
Definition: Statistics.hpp:491
bool operator==(const StatisticsIterator &other) const
Definition: Statistics.hpp:485
std::vector< std::unique_ptr< Statistics > >::const_iterator it_
Definition: Statistics.hpp:497
std::unique_ptr< Statistics > releaseStatistic(Statistics::Id id)
Definition: Statistics.hpp:577
IteratorRange< StatisticsIterator > StatisticsRange
Definition: Statistics.hpp:501
bool IsDemanded(const Statistics &statistics) const noexcept
Definition: Statistics.hpp:550
void PrintStatistics()
Print collected statistics to file. If no statistics have been collected, this is a no-op.
Definition: Statistics.cpp:164
bool IsDemanded(Statistics::Id id) const noexcept
Definition: Statistics.hpp:537
const StatisticsCollectorSettings & GetSettings() const noexcept
Definition: Statistics.hpp:511
StatisticsCollectorSettings Settings_
Definition: Statistics.hpp:622
std::vector< std::unique_ptr< Statistics > > CollectedStatistics_
Definition: Statistics.hpp:623
std::unordered_map< std::string, size_t > OutputFileCounter_
Definition: Statistics.hpp:626
void CollectDemandedStatistics(std::unique_ptr< Statistics > statistics)
Definition: Statistics.hpp:563
StatisticsRange CollectedStatistics() const noexcept
Definition: Statistics.hpp:517
File createOutputFile(std::string fileNameSuffix, bool includeCount=false)
Definition: Statistics.cpp:179
StatisticsCollector(StatisticsCollectorSettings settings)
Definition: Statistics.hpp:506
size_t NumCollectedStatistics() const noexcept
Definition: Statistics.hpp:524
Statistics Interface.
Definition: Statistics.hpp:31
util::Timer & GetTimer(const std::string &name)
Definition: Statistics.cpp:134
util::FilePath SourceFile_
Definition: Statistics.hpp:245
std::string_view GetName() const
Definition: Statistics.cpp:57
const util::FilePath & GetSourceFile() const
Definition: Statistics.cpp:63
std::list< std::pair< std::string, util::Timer > > TimerList
Definition: Statistics.hpp:69
Statistics::Id StatisticsId_
Definition: Statistics.hpp:244
Statistics(const Statistics::Id &statisticsId, util::FilePath sourceFile)
Definition: Statistics.hpp:73
MeasurementList Measurements_
Definition: Statistics.hpp:247
bool HasTimer(const std::string &name) const noexcept
Definition: Statistics.cpp:125
std::string Serialize(char fieldSeparator, char nameValueSeparator) const
Definition: Statistics.cpp:69
const Measurement & GetMeasurement(const std::string &name) const
Definition: Statistics.cpp:110
const T & GetMeasurementValue(const std::string &name) const
Definition: Statistics.hpp:130
util::Timer & AddTimer(std::string name)
Definition: Statistics.cpp:155
IteratorRange< MeasurementList::const_iterator > GetMeasurements() const
Definition: Statistics.cpp:119
IteratorRange< TimerList::const_iterator > GetTimers() const
Definition: Statistics.cpp:149
size_t GetTimerElapsedNanoseconds(const std::string &name) const
Definition: Statistics.hpp:155
bool HasMeasurement(const std::string &name) const noexcept
Definition: Statistics.cpp:101
Statistics::Id GetId() const noexcept
Definition: Statistics.hpp:79
std::variant< std::string, int64_t, uint64_t, double > Measurement
Definition: Statistics.hpp:66
std::list< std::pair< std::string, Measurement > > MeasurementList
Definition: Statistics.hpp:68
void AddMeasurement(std::string name, T value)
Definition: Statistics.hpp:174
size_t ns() const
Definition: time.hpp:83
#define JLM_ASSERT(x)
Definition: common.hpp:16
std::string CreateRandomAlphanumericString(std::size_t length)
Definition: strfmt.cpp:15
static const char * FunctionNameLabel_
Definition: Statistics.hpp:204
static const char * NumPointsToGraphAllocaNodes
Definition: Statistics.hpp:218
static const char * NumPointsToGraphMemoryNodes
Definition: Statistics.hpp:223
static const char * NumRvsdgNodes
Definition: Statistics.hpp:210
static const char * NumFirstOrderRecurrences
Definition: Statistics.hpp:236
static const char * NumPointsToGraphDeltaNodes
Definition: Statistics.hpp:219
static const char * NumThreeAddressCodes
Definition: Statistics.hpp:208
static const char * NumRvsdgNodesBefore
Definition: Statistics.hpp:211
static const char * NumPointsToGraphRegisterNodes
Definition: Statistics.hpp:224
static const char * NumSecondOrderRecurrences
Definition: Statistics.hpp:237
static const char * NumPointsToGraphNodes
Definition: Statistics.hpp:217
static const char * NumPointsToGraphMallocNodes
Definition: Statistics.hpp:222
static const char * NumPointsToGraphImportNodes
Definition: Statistics.hpp:220
static const char * NumRvsdgNodesAfter
Definition: Statistics.hpp:212
static const char * NumPointsToGraphExternallyAvailableNodes
Definition: Statistics.hpp:225
static const char * NumPointsToGraphExplicitEdges
Definition: Statistics.hpp:230
static const char * NumTotalRecurrences
Definition: Statistics.hpp:234
static const char * NumPointsToGraphLambdaNodes
Definition: Statistics.hpp:221
static const char * NumPointsToGraphEdges
Definition: Statistics.hpp:231
static const char * NumPointsToGraphNodesTargetsAllExternallyAvailable
Definition: Statistics.hpp:227
static const char * NumLoopVariablesTotal
Definition: Statistics.hpp:233
static const char * NumCfgNodes
Definition: Statistics.hpp:206
static const char * NumRvsdgInputsAfter
Definition: Statistics.hpp:215
static const char * NumConstantRecurrences
Definition: Statistics.hpp:235
static const char * NumThirdOrderRecurrences
Definition: Statistics.hpp:238
static const char * NumRvsdgInputsBefore
Definition: Statistics.hpp:214