Jlm
Statistics.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2020 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 
8 
10 #include <jlm/util/strfmt.hpp>
11 
12 #include <string_view>
13 
14 namespace jlm::util
15 {
16 // Mapping between each statistics id and identifier used when serializing the statistic
17 static const util::BijectiveMap<Statistics::Id, std::string_view> &
19 {
21  { Statistics::Id::AggregateAllocaSplitting, "AggregateAllocaSplitting" },
22  { Statistics::Id::Aggregation, "Aggregation" },
23  { Statistics::Id::AgnosticModRefSummarizer, "AgnosticModRefSummarizer" },
24  { Statistics::Id::AliasAnalysisPrecisionEvaluation, "AliasAnalysisPrecisionEvaluation" },
25  { Statistics::Id::AndersenAnalysis, "AndersenAnalysis" },
26  { Statistics::Id::Annotation, "Annotation" },
28  { Statistics::Id::ControlFlowRecovery, "ControlFlowRestructuring" },
29  { Statistics::Id::DataNodeToDelta, "DataNodeToDeltaStatistics" },
30  { Statistics::Id::DeadNodeElimination, "DeadNodeElimination" },
32  { Statistics::Id::IfConversion, "IfConversion" },
33  { Statistics::Id::JlmToRvsdgConversion, "ControlFlowGraphToLambda" },
34  { Statistics::Id::LoopStrengthReduction, "LoopStrengthReduction" },
35  { Statistics::Id::LoopUnrolling, "UNROLL" },
36  { Statistics::Id::LoopUnswitching, "LoopUnswitching" },
37  { Statistics::Id::InvariantValueRedirection, "InvariantValueRedirection" },
38  { Statistics::Id::MemoryStateEncoder, "MemoryStateEncoder" },
39  { Statistics::Id::PullNodes, "PULL" },
40  { Statistics::Id::PushNodes, "PUSH" },
41  { Statistics::Id::ReduceNodes, "RED" },
42  { Statistics::Id::RegionAwareModRefSummarizer, "RegionAwareModRefSummarizer" },
43  { Statistics::Id::RvsdgConstruction, "InterProceduralGraphToRvsdg" },
44  { Statistics::Id::RvsdgDestruction, "RVSDGDESTRUCTION" },
45  { Statistics::Id::RvsdgOptimization, "RVSDGOPTIMIZATION" },
46  { Statistics::Id::RvsdgTreePrinter, "RvsdgTreePrinter" },
47  { Statistics::Id::ScalarEvolution, "ScalarEvolution" },
48  { Statistics::Id::StoreValueForwarding, "StoreValueForwarding" },
49  };
50  // Make sure every Statistic is mentioned in the mapping
51  auto lastIdx = static_cast<size_t>(Statistics::Id::LastEnumValue);
52  auto firstIdx = static_cast<size_t>(Statistics::Id::FirstEnumValue);
53  JLM_ASSERT(mapping.Size() == lastIdx - firstIdx - 1);
54  return mapping;
55 }
56 
57 Statistics::~Statistics() = default;
58 
59 std::string_view
61 {
62  return GetStatisticsIdNames().LookupKey(StatisticsId_);
63 }
64 
65 const util::FilePath &
67 {
68  return SourceFile_;
69 }
70 
71 std::string
72 Statistics::Serialize(char fieldSeparator, char nameValueSeparator) const
73 {
74  std::ostringstream ss;
75 
76  ss << GetName() << fieldSeparator;
77  ss << GetSourceFile().to_str();
78 
79  for (const auto & [mName, measurement] : Measurements_)
80  {
81  if (ss.tellp() != 0)
82  ss << fieldSeparator;
83 
84  ss << mName << nameValueSeparator;
85  std::visit(
86  [&](const auto & value)
87  {
88  ss << value;
89  },
90  measurement);
91  }
92  for (const auto & [mName, timer] : Timers_)
93  {
94  if (ss.tellp() != 0)
95  ss << fieldSeparator;
96 
97  ss << mName << "[ns]" << nameValueSeparator << timer.ns();
98  }
99 
100  return ss.str();
101 }
102 
103 bool
104 Statistics::HasMeasurement(const std::string & name) const noexcept
105 {
106  for (const auto & [mName, _] : Measurements_)
107  if (mName == name)
108  return true;
109  return false;
110 }
111 
113 Statistics::GetMeasurement(const std::string & name) const
114 {
115  for (const auto & [mName, measurement] : Measurements_)
116  if (mName == name)
117  return measurement;
118  JLM_UNREACHABLE("Unknown measurement");
119 }
120 
123 {
124  return { Measurements_.begin(), Measurements_.end() };
125 }
126 
127 bool
128 Statistics::HasTimer(const std::string & name) const noexcept
129 {
130  for (const auto & [mName, _] : Timers_)
131  if (mName == name)
132  return true;
133  return false;
134 }
135 
136 util::Timer &
137 Statistics::GetTimer(const std::string & name)
138 {
139  for (auto & [mName, timer] : Timers_)
140  if (mName == name)
141  return timer;
142  JLM_UNREACHABLE("Unknown Timer");
143 }
144 
145 const util::Timer &
146 Statistics::GetTimer(const std::string & name) const
147 {
148  return const_cast<Statistics *>(this)->GetTimer(name);
149 }
150 
153 {
154  return { Timers_.begin(), Timers_.end() };
155 }
156 
157 util::Timer &
158 Statistics::AddTimer(std::string name)
159 {
160  JLM_ASSERT(!HasTimer(name));
161  Timers_.emplace_back(std::make_pair(std::move(name), util::Timer()));
162  auto & timer = Timers_.back().second;
163  return timer;
164 }
165 
166 void
168 {
169  if (NumCollectedStatistics() == 0)
170  return;
171 
172  auto file = createOutputFile("statistics.log");
173  file.open("w");
174 
175  for (auto & statistics : CollectedStatistics())
176  {
177  fprintf(file.fd(), "%s\n", statistics.Serialize(' ', ':').c_str());
178  }
179 }
180 
181 File
182 StatisticsCollector::createOutputFile(std::string fileNameSuffix, bool includeCount)
183 {
185 
186  auto directory = Settings_.GetOrCreateOutputDirectory();
187 
188  // If the fileNameSuffix should have a count included, place it before the '.' (or at the end)
189  if (includeCount)
190  {
191  size_t count = OutputFileCounter_[fileNameSuffix]++;
192  auto firstDot = fileNameSuffix.find('.');
193  if (firstDot == std::string::npos)
194  firstDot = fileNameSuffix.size();
195 
196  fileNameSuffix =
197  strfmt(fileNameSuffix.substr(0, firstDot), "-", count, fileNameSuffix.substr(firstDot));
198  }
199 
200  std::string fileName;
201  if (!Settings_.GetModuleName().empty())
202  fileName += Settings_.GetModuleName() + "-";
203  if (!Settings_.GetUniqueString().empty())
204  fileName += Settings_.GetUniqueString() + "-";
205  fileName += fileNameSuffix;
206 
207  auto fullPath = directory.Join(fileName);
208  if (fullPath.Exists())
209  throw Error("The generated output file name already exists: " + fullPath.to_str());
210 
211  return File(fullPath);
212 }
213 
214 }
std::size_t Size() const noexcept
const std::string & to_str() const noexcept
Definition: file.hpp:275
bool HasOutputDirectory() const noexcept
Definition: Statistics.hpp:355
const std::string & GetUniqueString() const noexcept
Definition: Statistics.hpp:417
const FilePath & GetOrCreateOutputDirectory() const noexcept
Definition: Statistics.hpp:377
const std::string & GetModuleName() const noexcept
Definition: Statistics.hpp:399
void PrintStatistics()
Print collected statistics to file. If no statistics have been collected, this is a no-op.
Definition: Statistics.cpp:167
StatisticsCollectorSettings Settings_
Definition: Statistics.hpp:633
std::unordered_map< std::string, size_t > OutputFileCounter_
Definition: Statistics.hpp:637
StatisticsRange CollectedStatistics() const noexcept
Definition: Statistics.hpp:528
File createOutputFile(std::string fileNameSuffix, bool includeCount=false)
Definition: Statistics.cpp:182
size_t NumCollectedStatistics() const noexcept
Definition: Statistics.hpp:535
Statistics Interface.
Definition: Statistics.hpp:31
util::Timer & GetTimer(const std::string &name)
Definition: Statistics.cpp:137
util::FilePath SourceFile_
Definition: Statistics.hpp:256
std::string_view GetName() const
Definition: Statistics.cpp:60
const util::FilePath & GetSourceFile() const
Definition: Statistics.cpp:66
Statistics::Id StatisticsId_
Definition: Statistics.hpp:255
MeasurementList Measurements_
Definition: Statistics.hpp:258
bool HasTimer(const std::string &name) const noexcept
Definition: Statistics.cpp:128
std::string Serialize(char fieldSeparator, char nameValueSeparator) const
Definition: Statistics.cpp:72
const Measurement & GetMeasurement(const std::string &name) const
Definition: Statistics.cpp:113
util::Timer & AddTimer(std::string name)
Definition: Statistics.cpp:158
IteratorRange< MeasurementList::const_iterator > GetMeasurements() const
Definition: Statistics.cpp:122
IteratorRange< TimerList::const_iterator > GetTimers() const
Definition: Statistics.cpp:152
bool HasMeasurement(const std::string &name) const noexcept
Definition: Statistics.cpp:104
std::variant< std::string, int64_t, uint64_t, double > Measurement
Definition: Statistics.hpp:69
#define JLM_ASSERT(x)
Definition: common.hpp:16
#define JLM_UNREACHABLE(msg)
Definition: common.hpp:43
static std::string strfmt(Args... args)
Definition: strfmt.hpp:35
static const util::BijectiveMap< Statistics::Id, std::string_view > & GetStatisticsIdNames()
Definition: Statistics.cpp:18