2
3
4
5
6
14#include <unordered_map>
21#include <Iterators.hpp>
31 static constexpr auto symbol =
"ms";
36 static constexpr auto symbol =
"µs";
41 static constexpr auto symbol =
"s";
46 template<std::integral T>
48 return static_cast<
int>(std::log(val + 1) / std::log(10)) + 1;
53
54
55
61
62
63
64
65 TimingEvent(
const detail::TP &start,
const detail::TP &end)
noexcept;
68
69
70
71
74 return std::chrono::duration_cast<T>(end - start).count();
79
80
81
82
85 T min, max, avg, stddev, med, sum;
89
90
91
93 std::unordered_map<std::string, std::vector<TimingEvent>> events;
98
99
100
101
105
106
107
108
109
110 void addEvent(detail::TP start, detail::TP end,
const std::string &name);
113
114
115
116
117
120 using Res =
decltype(std::declval<TimingEvent>().duration<T>());
123 Res max = std::numeric_limits<Res>::min();
124 Res min = std::numeric_limits<Res>::max();
125 const auto &eventList = events.at(eventName);
126 std::vector<Res> results;
127 results.reserve(eventList.size());
128 for (
const auto &evt : eventList) {
129 auto val = evt.duration<T>();
131 results.emplace_back(val);
133 max = std::max(max, val);
134 min = std::min(min, val);
137 Res mean = sum / eventList.size();
138 std::ranges::sort(results);
140 if (results.empty()) {
142 }
else if (results.size() % 2 == 0) {
143 med = (results[results.size() / 2] + results[results.size() / 2 - 1]) / 2;
145 med = results[results.size() / 2];
148 auto stddev =
static_cast<Res>(std::sqrt(sqSum / eventList.size() - mean * mean));
149 return Result<Res>{.min=min, .max=max, .avg=mean, .stddev=stddev, .med = med, .sum=sum};
154
155
156
157
158
159
160
162 void print(
const std::string &eventName, std::ostream &os,
int nameWidth = 0,
int valWidth = 0)
const {
163 auto [min, max, avg, stddev, med, sum] = getResult<T>(eventName);
165 os <<
"-- " << std::setw(nameWidth) << std::left << eventName <<
": \tmin: " << std::setw(valWidth)
166 << std::left << min << s
167 <<
", max: " << std::setw(valWidth) << std::left << max << s <<
", avg : " << std::setw(valWidth)
168 << std::left << avg << s
169 <<
", std: " << std::setw(valWidth) << std::left << stddev << s <<
", median: " << std::setw(valWidth)
171 << s <<
", total: " << sum << s <<
"\n";
175
176
177
178
179 bool has(
const std::string &event)
const noexcept {
180 return events.contains(event);
184
185
186
187
190 using ResT =
decltype(getResult<T>(
"").min);
191 constexpr auto NumFields =
sizeof(
Result<ResT>) /
sizeof(T);
194 std::array<
int, NumFields> valWidths{0};
195 std::vector<Result<ResT>> results;
196 for (
const auto &[name, _] : events) {
197 nameWidth = std::max(nameWidth,
static_cast<
int>(name.length()) + 1);
198 results.emplace_back(getResult<T>(name));
199 const auto fields = std::bit_cast<std::array<ResT, NumFields>>(results.back());
200 for (
auto [f, fWidth] : iterators::zip(fields, valWidths)) {
201 fWidth = std::max(fWidth,
static_cast<
int>(detail::printLen(f) + 1));
205 for (
auto [name, res] : iterators::zip(events | std::views::keys, results)) {
206 os <<
"-- " << std::setw(nameWidth)
207 << std::left << name <<
": \tmin: " << std::setw(valWidths[0]) << std::left << res.min << s
208 <<
", max: " << std::setw(valWidths[1]) << std::left << res.max << s
209 <<
", avg : " << std::setw(valWidths[2]) << std::left << res.avg << s
210 <<
", std: " << std::setw(valWidths[3]) << std::left << res.stddev << s
211 <<
", median: " << std::setw(valWidths[4]) << std::left << res.med << s
212 <<
", total: " << std::setw(valWidths[5]) << std::left << res.sum << s <<
"\n";
218
219
220
227
228
232
233
237
238
239
240
244
245
246
247
250 return std::chrono::duration_cast<T>(std::chrono::high_resolution_clock::now() - startTp).count();
256
257
263
264
265
266
270
271
Profiler that manages multiple events.
Definition Profiler.hpp:92
auto getResult(const std::string &eventName) const
Definition Profiler.hpp:119
void print(const std::string &eventName, std::ostream &os, int nameWidth=0, int valWidth=0) const
Definition Profiler.hpp:162
bool has(const std::string &event) const noexcept
Definition Profiler.hpp:179
void addEvent(detail::TP start, detail::TP end, const std::string &name)
Definition Profiler.cpp:39
void addEvent(const TimingEvent &event, const std::string &name)
Definition Profiler.cpp:35
void printAll(std::ostream &os) const
Definition Profiler.hpp:189
Stop watch that automatically adds a timing event to a profiler at destruction.
Definition Profiler.hpp:258
~ScopeWatch()
Definition Profiler.cpp:31
ScopeWatch(Profiler &profiler, std::string eventName)
Definition Profiler.cpp:26
Used to measure time between start a start and a stop event.
Definition Profiler.hpp:221
StopWatch()
Definition Profiler.cpp:22
TimingEvent getTiming() const
Definition Profiler.cpp:18
auto elapsed() const
Definition Profiler.hpp:249
void start()
Definition Profiler.cpp:14
Definition heuristics.hpp:33
Definition basic_structures.cpp:10
Profiling result.
Definition Profiler.hpp:84
Represents an event with a duration.
Definition Profiler.hpp:56
auto duration() const noexcept
Definition Profiler.hpp:73
detail::TP end
end point of the event
Definition Profiler.hpp:58
TimingEvent(const detail::TP &start, const detail::TP &end) noexcept
Definition Profiler.cpp:12
detail::TP start
start point of the event
Definition Profiler.hpp:57
Definition Profiler.hpp:27