Chi-Tech
TimingLog.cc
Go to the documentation of this file.
1#include "TimingLog.h"
2
3#include "utils/chi_timer.h"
4
5#include "chi_runtime.h"
6
8
9#include <sstream>
10
11namespace chi
12{
13
14TimingBlock&
15TimingLog::CreateTimingBlock(const std::string& name,
16 const std::string& parent_name /*=""*/)
17{
18 ChiInvalidArgumentIf(timing_blocks_.count(name) != 0,
19 "TimingBlock with name \"" + name +
20 "\" already exists"
21 " in the logger");
22 auto block_ptr = std::make_unique<TimingBlock>(name);
23 auto saved_pointer = &(*block_ptr);
24 timing_blocks_[name] = std::move(block_ptr);
25
26 if (parent_name.empty())
27 {
28 if (name != "ChiTech")
29 {
30 auto iter = timing_blocks_.find("ChiTech");
32 iter == timing_blocks_.end(),
33 "Bad error, could not fine the \"ChiTech\" timing block");
34
35 iter->second->AddChild(*saved_pointer);
36 }
37
38 return *saved_pointer;
39 }
40
41 auto iter = timing_blocks_.find(parent_name);
42
44 "Parent name \"" + parent_name + "\" does not exist.");
45
46 auto& parent = iter->second;
47 parent->AddChild(*saved_pointer);
48
49 return *saved_pointer;
50}
51
53TimingLog::CreateOrGetTimingBlock(const std::string& name,
54 const std::string& parent_name /*=""*/)
55{
56 auto iter = timing_blocks_.find(name);
57
58 if (iter == timing_blocks_.end()) return CreateTimingBlock(name, parent_name);
59
60 return *iter->second;
61}
62
63TimingBlock& TimingLog::GetTimingBlock(const std::string& name)
64{
65 auto iter = timing_blocks_.find(name);
66
68 "Timing block with name \"" + name +
69 "\" does not exist.");
70
71 return *iter->second;
72}
73
74// ##################################################################
75
76TimingBlock::TimingBlock(const std::string& name) : name_(name) {}
77
79{
81}
82
84{
85 const double delta_t = Chi::program_timer.GetTime() - reference_time_;
86 total_time_ += delta_t;
87 num_occurences_ += 1;
88 last_delta_time_ = delta_t;
89}
90
92
93double TimingBlock::TotalTime() const { return total_time_; }
94
96{
97 if (num_occurences_ == 0) return 0.0;
98
99 return total_time_ / static_cast<double>(num_occurences_);
100}
101
103{
104 return last_delta_time_;
105}
106
107void TimingBlock::AddChild(const TimingBlock& child_block)
108{
109 children_.push_back(&child_block);
110}
111
113{
114 if (name_ == "ChiTech") TimeSectionEnd();
115
116 std::vector<std::vector<std::string>> string_matrix;
117
118 AppendGraphEntry(string_matrix, nullptr, "");
119
120 const size_t J = 5;
121 const size_t I = string_matrix.size();
122
123 std::vector<size_t> max_col_widths(J, 0);
124 for (size_t i = 0; i < I; ++i)
125 for (size_t j = 0; j < J; ++j)
126 max_col_widths[j] =
127 std::max(max_col_widths[j], string_matrix[i][j].size());
128
129 std::vector<std::string> headers = {"Section Name",
130 "#calls",
131 "Total time[s]",
132 "Average time[s]",
133 "% of parent"};
134
135 for (size_t j = 0; j < J; ++j)
136 max_col_widths[j] = std::max(max_col_widths[j], headers[j].size());
137
138 /**Lambda to left pad an entry.*/
139 auto LeftPad = [](std::string& entry, size_t width)
140 {
141 const size_t pad_size = width - entry.size();
142 entry = std::string(pad_size, ' ').append(entry);
143 };
144 /**Lambda to right pad an entry.*/
145 auto RightPad = [](std::string& entry, size_t width)
146 {
147 const size_t pad_size = width - entry.size();
148 entry.append(std::string(pad_size, ' '));
149 };
150
151 std::stringstream outstr;
152
153 auto HDIV = [&outstr, &max_col_widths]()
154 {
155 outstr << "*-";
156 for (size_t j = 0; j < J; ++j)
157 {
158 outstr << std::string(max_col_widths[j] + 1, '-');
159 if (j < (J - 1)) outstr << "*-";
160 }
161 outstr << "*\n";
162 };
163
164 HDIV();
165
166 outstr << "| ";
167 for (size_t j = 0; j < J; ++j)
168 {
169 if (j == 0) RightPad(headers[j], max_col_widths[j]);
170 else
171 LeftPad(headers[j], max_col_widths[j] + 1);
172 outstr << headers[j] << " |";
173 }
174 outstr << "\n";
175
176 HDIV();
177
178 for (size_t i = 0; i < I; ++i)
179 {
180 outstr << "| ";
181 for (size_t j = 0; j < J; ++j)
182 {
183 if (j == 0) RightPad(string_matrix[i][j], max_col_widths[j]);
184 else
185 LeftPad(string_matrix[i][j], max_col_widths[j] + 1);
186 outstr << string_matrix[i][j] << " |";
187 }
188 outstr << "\n";
189 }
190
191 HDIV();
192
193 return outstr.str();
194}
195
196// NOLINTBEGIN(misc-no-recursion)
198 std::vector<std::vector<std::string>>& string_matrix,
199 const TimingBlock* parent,
200 const std::string& indent) const
201{
202 std::vector<std::string> entry;
203
204 const double parent_total_time = parent ? parent->TotalTime() : 0.0;
205 const double relative_time =
206 parent_total_time > 1.0e-12 ? total_time_ * 100.0 / parent_total_time : 0.0;
207
208 entry.push_back(indent + name_);
209 entry.push_back(std::to_string(num_occurences_));
210
211 {
212 char buffer[20];
213 ChiLogicalErrorIf(snprintf(buffer, 20, "%.5g", total_time_ / 1000.0) < 0,
214 "Failed to convert total_time = " +
215 std::to_string(total_time_));
216 entry.push_back(buffer);
217 }
218
219 {
220 char buffer[20];
221 ChiLogicalErrorIf(snprintf(buffer, 20, "%.5g", AverageTime() / 1000.0) < 0,
222 "Failed to convert AverageTime = " +
223 std::to_string(AverageTime()));
224 entry.push_back(buffer);
225 }
226
227 {
228 char buffer[10];
229 ChiLogicalErrorIf(snprintf(buffer, 10, "%.2f%%", relative_time) < 0,
230 "Failed to convert relative_time = " +
231 std::to_string(relative_time));
232 entry.push_back(parent ? buffer : "--");
233 }
234
235 string_matrix.push_back(std::move(entry));
236
237 for (auto& child_ptr : children_)
238 child_ptr->AppendGraphEntry(string_matrix, this, indent + " ");
239}
240// NOLINTEND(misc-no-recursion)
241
242} // namespace chi
#define ChiLogicalErrorIf(condition, message)
#define ChiInvalidArgumentIf(condition, message)
static chi::Timer program_timer
Definition: chi_runtime.h:79
double GetTime() const
Definition: chi_timer.cc:23
void TimeSectionEnd()
Definition: TimingLog.cc:83
void AppendGraphEntry(std::vector< std::vector< std::string > > &string_matrix, const TimingBlock *parent, const std::string &indent) const
Definition: TimingLog.cc:197
double TotalTime() const
Definition: TimingLog.cc:93
TimingBlock(const std::string &name)
Definition: TimingLog.cc:76
double last_delta_time_
Definition: TimingLog.h:84
double reference_time_
Definition: TimingLog.h:83
void TimeSectionBegin()
Definition: TimingLog.cc:78
double total_time_
Definition: TimingLog.h:82
void AddChild(const TimingBlock &child_block)
Definition: TimingLog.cc:107
const std::string name_
Definition: TimingLog.h:80
double LastDelta() const
Definition: TimingLog.cc:102
double AverageTime() const
Definition: TimingLog.cc:95
size_t NumberOfOccurences() const
Definition: TimingLog.cc:91
std::vector< const TimingBlock * > children_
Definition: TimingLog.h:85
size_t num_occurences_
Definition: TimingLog.h:81
std::string MakeGraphString()
Definition: TimingLog.cc:112
std::map< std::string, std::unique_ptr< TimingBlock > > timing_blocks_
Definition: TimingLog.h:38
TimingBlock & CreateTimingBlock(const std::string &name, const std::string &parent_name="")
Definition: TimingLog.cc:15
TimingBlock & CreateOrGetTimingBlock(const std::string &name, const std::string &parent_name="")
Definition: TimingLog.cc:53
TimingBlock & GetTimingBlock(const std::string &name)
Definition: TimingLog.cc:63